Использование Private API в приложениях для App Store

в 8:06, , рубрики: development, hack, iOS, ipad, iphone, mobile development, xcode, кодинг, разработка под iOS, метки: , , , , , , ,

Я думаю, что большинство iOS разработчиков так или иначе сталкивались с тем, что по правилам Apple не удавалось сделать какие-либо функции. Часто это бывает связано с тем, что определенные методы попали в раздел private. При попытке опубликовать приложение с их использованием последует его отклонение (пункт 2.5 Apple Review Guidelines).

Использование Private API в приложениях для App Store

Под катом я расскажу, как можно частично снять это ограничение.

Скрыть крупные нарушения правил таким образом не удастся, ведь из функционала вашего приложения будет видно, что оно использует что-то запретное (передача файлов по bluetooth, например), но вот для каких-либо изменений стандартного UI и чего-то подобного этот способ подойдет идеально.

Итак, предположим мы хотим изменить цвет UISwitch, но на iOS 4 (tintColor появился в iOS 5). Это можно сделать с помощью следующего кода:

[testSwitch setAlternateColors:true];

Вроде, все просто, но этого метода нету в документации UISwitch, а следовательно — использовать его нельзя. Скрыть это можно используя возможности Objective-C Runtime

Итак, далее небольшая пошаговая инструкция:

  1. Собираем NSString по кусочкам, чтобы анализаторы кода не заметили его название целиком:
    NSString *nameOfMethod = @””;
    for (NSString *s in [NSArray arrayWithObjects:@"set",@"Alt",@"ernate",@"Colors:",nil])
    nameOfMethod = [nameOfMethod stringByAppendingString:s];
    const char *nameOfMethodUTF8 = [nameOfMethod UTF8String];
    

  2. Перебираем методы UISwitch, пока не найдем желаемый:
        SEL methodSel = nil;
        Method *methods = class_copyMethodList([UISwitch class], &count);
        i = 0;
        while(i < count)   {
            SEL s = method_getName(methods[i]);
            if (0 == strcmp(sel_getName(s), methodNameUTF8String))  {
                methodSel = s;
                
                i = count;
            }
        }
    

  3. Вызываем функцию для соответствующего объекта (testSwitch):
    if (methodSel != nil) {
            IMP m_imp = method_getImplementation(methodsList[i]);
            m_imp(theSwitch, methodSel, YES);
    }
    free(methods);
    

Вуаля, мы обошли это ограничение, но, пожалуйста, прежде чем использовать этот метод подумайте, почему Apple его заблокировала.

PS: Для проверки приложения на использование private api можно использовать приложение App Scanner

Автор: itruf


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js