Просмотр свойств, соответствующих UI_APPEARANCE_SELECTOR

Я пытаюсь использовать свойство backgroundColor в UIView.

Перед тем, как свистнуть, я делаю следующее:

@implementation UIView (Cat1)
+(void)load {
NSArray *selectors = @[
                     //Highliter swizzling
                     NSStringFromSelector(@selector(setBackgroundColor:)),
                     NSStringFromSelector(@selector(backgroundColor))
                     ];

[[self appearance] setBackgroundColor:[UIColor redColor]];

for (NSString *name in selectors) {
    SEL originalSelector = NSSelectorFromString(name);
    SEL swizzledSelector = NSSelectorFromString([NSString stringWithFormat:@"swizzled_%@",name]);
    Method originalMethod = class_getInstanceMethod(self, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
    class_addMethod(self,
                    originalSelector,
                    class_getMethodImplementation(self, originalSelector),
                    method_getTypeEncoding(originalMethod));
    class_addMethod(self,
                    swizzledSelector,
                    class_getMethodImplementation(self, swizzledSelector),
                    method_getTypeEncoding(swizzledMethod));
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

затем, когда вызывается метод swizzled, я ничего не делаю, кроме вызова оригинала:

-(void)swizzled_setBackgroundColor:(UIColor *)color {

[self iio_swizzled_setBackgroundColor:color];
}

Затем происходит следующий сбой:2017-03-08 19:04:37.863 Develop-InsertViewer[69285:7916872] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Please file a radar on UIKit if you see this assertion.' *** First throw call stack: ( 0 CoreFoundation 0x0000000108506e65 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000107c7ddeb objc_exception_throw + 48 2 CoreFoundation 0x0000000108506cca +[NSException raise:format:arguments:] + 106 3 Foundation 0x00000001078ca5a2 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 169 4 UIKit 0x0000000106227b35 PushNextClassForSettingIMP + 469 5 UIKit 0x000000010622810a TaggingAppearanceObjectSetterIMP + 37 6 InsertFramework 0x00000001071332be -[UIView(Cat1) swizzled_setBackgroundColor:] + 62 7 UIKit 0x0000000105d78fca -[UILabel _commonInit] + 238 8 UIKit 0x0000000105d7913d -[UILabel initWithFrame:] + 94 9 UIKit 0x0000000105b9cc4e -[UIView init] + 62 10 0x0000000105533300 _TTOFCSo7UILabelcfT_S_ + 16 11 0x0000000105532e44 _TFCSo7UILabelCfT_S_ + 68 12 0x0000000105569be3 _TFC12InsertViewer21StarterViewControllercfT5coderCSo7NSCoder_GSqS0__ + 51 13 0x0000000105569d2d _TToFC12InsertViewer21StarterViewControllercfT5coderCSo7NSCoder_GSqS0__ + 45 14 UIKit 0x0000000105ecb7db -[UIClassSwapper initWithCoder:] + 241 15 UIKit 0x000000010609f822 UINibDecoderDecodeObjectForValue + 705 16 UIKit 0x000000010609f558 -[UINibDecoder decodeObjectForKey:] + 278 17 UIKit 0x0000000105ecb4b1 -[UIRuntimeConnection initWithCoder:] + 180 18 UIKit 0x000000010609f822 UINibDecoderDecodeObjectForValue + 705 19 UIKit 0x000000010609f9e3 UINibDecoderDecodeObjectForValue + 1154 20 UIKit 0x000000010609f558 -[UINibDecoder decodeObjectForKey:] + 278 21 UIKit 0x0000000105eca6c3 -[UINib instantiateWithOwner:options:] + 1255 22 UIKit 0x0000000106232c40 -[UIStoryboard instantiateViewControllerWithIdentifier:] + 181 23 UIKit 0x0000000106232d93 -[UIStoryboard instantiateInitialViewController] + 69 24 UIKit 0x0000000105b0dfa6 -[UIApplication _loadMainStoryboardFileNamed:bundle:] + 94 25 UIKit 0x0000000105b0e2d6 -[UIApplication _loadMainInterfaceFile] + 260 26 UIKit 0x0000000105b0cb54 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1390 27 UIKit 0x0000000105b09e7b -[UIApplication workspaceDidEndTransaction:] + 188 28 FrontBoardServices 0x000000010b41e754 -[FBSSerialQueue _performNext] + 192 29 FrontBoardServices 0x000000010b41eac2 -[FBSSerialQueue _performNextFromRunLoopSource] + 45 30 CoreFoundation 0x0000000108432a31 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 31 CoreFoundation 0x000000010842895c __CFRunLoopDoSources0 + 556 32 CoreFoundation 0x0000000108427e13 __CFRunLoopRun + 867 33 CoreFoundation 0x0000000108427828 CFRunLoopRunSpecific + 488 34 UIKit 0x0000000105b097cd -[UIApplication _run] + 402 35 UIKit 0x0000000105b0e610 UIApplicationMain + 171 36 Develop-InsertViewer 0x00000001055ae752 main + 114 37 libdyld.dylib 0x00000001095a192d start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException

Это также происходит, если я делаю [собственное появление] в другом классе, таком как UIToolBar

Есть идеи??


person yanivH    schedule 08.03.2017    source источник


Ответы (1)


Система внешнего вида сводит все свойства к одной реализации TaggingAppearanceObjectSetterIMP. Эта реализация проверяет имя селектора (используя _UIAppearanceTagObjectForSelector) и ищет его в связанном кэше объектов (хранится в __UIAppearanceCustomizedSelectorsAssociationKey). Если его там еще нет, он вызывает _TagForSelectorWithAxes, чтобы выяснить, что сопоставлено с этим селектором, и обновить кеш.

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

Основная проблема, как минимум, заключается в том, что имя метода должно быть setBackgroundColor, а не swizzled_setBackgroundColor. Вы можете немного обойти это, используя реальную функцию реализации, а не метод. Вы можете посмотреть NSNotificationCenter+RNSwizzle.m для пример того, как это сделать своими руками.

Я не удивлюсь, если после исправления этого вы все равно столкнетесь с другими тонкими проблемами. Моя рекомендация (ну, моя рекомендация: «никогда не качайте рабочий код, он слишком хрупок», но если вы игнорируете эту рекомендацию…) загрузите код внешнего вида в Hopper и проследите реализации, чтобы убедиться, что все совпадает. Это не настолько сложно, и режим псевдокода Хоппера в значительной степени покажет вам, что происходит (мне потребовалось около 2 минут, чтобы понять то, что я разместил здесь). Тем не менее, это очень сложная деталь реализации, и она может легко измениться без предупреждения (что приведет к новым сбоям). Если вы можете сделать это без swizzling, я настоятельно рекомендую это.

person Rob Napier    schedule 08.03.2017
comment
Цитируя Милу Йовович в «Пятом элементе»: Большой BADABOOM… Спасибо, Роб! - person yanivH; 08.03.2017