Начинающим разработчикам: маленькая хитрость для публикации в App Store

20

AppStore

В комментариях к прошлой статье, посвященной мифам и реалиям работы с App Store, высказалось достаточно много читателей, приложения которых по тем или иным причинам отклонялись. Это навело меня на мысль рассказать об одном способе, который помогает обойти строгих проверяющих AppStore. Ниже я вкратце опишу суть этого «лайфхака» с пояснениями и примерами кода.

Популярная причина отказа в публикации – использование непубличного API (пункт 2.5 Apple Review Guidelines). Проверить, использует ли ваше приложение приватные функции, можно, например, с помощью такой утилиты: http://www.chimpstudios.com/appscanner/

Проект, к сожалению, недавно перестал поддерживаться, но местами еще актуален. Провериться стоит всем, даже если вы добропорядочный разработчик и ни разу не слышали имени Erica Sadun. Проблема может быть в ваших самостоятельно реализованных методах: если название какого-либо из них совпадет с непубличным системным методом, приложение будет отклонено по тому же пункту 2.5 ARG.

На мой взгляд, можно выделить два больших класса задач, для решения которых используется непубличное API:

  1. добавление в iOS несуществующей функциональности (работа на прямую с файловой системой, захват экрана и т.д.)
  2. кастомизация стандартных элементов управления (Apple до iOS 5 предоставляла очень ограниченные возможности настройки стандартных элементов управления)

Приложениям из пункта 1 не видать публикации в App Store, даже если проверка на приватные функции будет пройдена, так как из описания приложения очевидно, что запрещенные технологии все же используются. Второй случай более интересен, ведь можно реализовать собственные элементы управления, похожие на системные, но «с блэкджеком и …», то есть кастомизируемые. Эта задача достаточно сложная и трудозатратная, особенно если элемент управления активно использует анимацию.

Предположим, что наша задача — написать приложение с поддержкой iOS 4 и выше, и реализовать в нем переключатель оранжевого цвета, как в iOS Settings – Airplane Mode Switch:

Настройки

Следующий код позволит сделать, что требуется:

(void)viewDidLoad
{
[super viewDidLoad];
[testSwitch setAlternateColors:YES];
}

Но setAlternateColors — непубличный метод, он не объявлен в официальном описании UISwitch. Использование этого метода обнаруживается обычным strings и влечет за собой отказ в публикации в App Store. Для маскировки использования непубличного метода можно воспользоваться возможностями Objective-C Runtime, то есть не посылать сообщение объекту, а вызвать соответствующую функцию, найденную по селектору. Теперь об этом подробнее:

  1. Объявляем имя сообщения setAlternateColors как составленное из частей слов:

    NSString* methodName = @””;
    for (NSString *s in [NSArray arrayWithObjects:@"set",
    @"Alternate",
    @"Colors:",
    nil])
    methodName = [methodName stringByAppendingString:s];
    const char *methodNameUTF8String = [methodName UTF8String];

  2. Перебираем методы класса UISwitch, пока не найдем указатель на метод, который по имени совпадает с setAlternateColors:

    SEL methodSelector = nil;
    Method *methodsList = class_copyMethodList([UISwitch class], &count);
    for (i = 0; i < count; i++) { SEL s = method_getName(methodsList[i]); if (0 == strcmp(sel_getName(s), methodNameUTF8String)) { methodSelector = s; break; } }

  3. Вызываем функцию у соответствующего объекта (в нашем случае это theSwitch), используя селектор из п.2 и параметры, которые нужно использовать. В нашем случае это YES, как и в самом первом примере кода:

    if (nil != methodSelector)
    {
    IMP m_imp = method_getImplementation(methodsList[i]);
    m_imp(theSwitch, methodSelector, YES);
    }
    free(methodsList);

Тем самым получаем, что приватный метод не встречается целым словом в ASCII строках бинарного файла (как раз то, что показывает strings) и не может быть обнаружен системами поиска непубличных API-вызовов.

В заключение хочу напомнить, что перед использованием данного метода — и всегда перед использованием хитростей и обходных путей — нужно попытаться понять, зачем ограничения были установлены и стоит ли вообще их обходить? Не исключено, что текущие ограничения имеют вполне объяснимые причины.

20 комментариев

  1. 0

    Статья как для Xабра 🙂
    (отправлено из приложения AppleInsider.ru)

  2. 0
    Сирожа

    Игры с огнем
    (отправлено из приложения AppleInsider.ru)

    • 0

      Сирожа, согласна, лучше играть по правилам 🙂 Можно воспринимать эту статью как изучение возможностей Objective C Runtime для использования с других более сложных и интересных штуках.

  3. 0
    Ренат Гришин

    Какая ты умная и хитрая 🙂

  4. 0
    Павел Семенов

    Кстати, по-моему, в последних версиях XCode появляется сообщение в консоли, что ты назвал свой класс как уже существующий в приватных API. Личный пример: писал синглтон — назвал его DeviceManager (.m, .h) — получил сообщение, что оный уже существует в каком-то приватном фреймворке.
    (отправлено из приложения AppleInsider.ru)

    • 0

      Павел, Такие проверки действительно есть. Но можно названием метода попасть в еще не отрелиженные функции например, так что лучше по возможности использовать соответствующие префиксы.

  5. 0

    Напоминает то, как я прятал ShellExecute от антивирусов с эвристическим анализатором в университетские времена ) они палили таблицу экспорта и константные строки в ресурсах. Приходилось получать функцию через GetProcAddress конкатенируя название из составляющих.
    Эх… вот уж не думал, что опыт пригодится ))

    @ssgreg

  6. 0
    Евгений

    Не делайте так.

  7. 0

    десткий сад, честное слово =)

  8. 0
    TheMengzor

    а java+script нельзя сделать?

  9. 0

    Ксюша молодец. Настоящий программист всегда найдёт способ добится нужного результата, даже если придётся идти в обход.

  10. 0
    AMALIAWeiss

    If you are willing to buy real estate, you will have to get the loan. Furthermore, my brother commonly utilizes a commercial loan, which occurs to be the most useful.

  11. 0
    home loans

    I opine that to receive the credit loans from creditors you must have a great motivation. Nevertheless, once I have received a secured loan, just because I was willing to buy a building.

Авторизуйтесь Чтобы оставить комментарий