UILabel 类别块 属性 在检查主线程时崩溃

UILabel category block property crash when main thread checked

@interface UILabel (Chainable)
@property (nonatomic, readonly) UILabel *(^color)(NSString *value);
@end

@implementation UILabel (Chainable)
- (UILabel *(^)(NSString *value))color {
  return ^(NSString *value) {
    self.textColor = UIColor.whiteColor; // 
    return self;
  };
}
@end

UILabel *label = [UILabel new].color(@"0xffffff");

为什么这样编码会导致崩溃:

Thread 1: EXCBADACCESS (code=1, address=0x0) when xcode -> edit scheme -> Diagnostics -> main thread checker is selected

仅在使用调试模式时崩溃。

不要使用名称 UILabel 您可以使用 UILabelCustom 接口和实现,然后您可以这样称呼它

UILabelCustom *label = [UILabelCustom new].color(@"0xffffff");

或者你也可以继承到原生的UILabel

问题是名字。 -color 是 UILabel 上的现有扩展。我相信它被弃用的时间超过 iOS 已经 public (textColor 来自 iOS 2),但它仍然存在:

dsdump /System/iOSSupport/System/Library/PrivateFrameworks/UIKitCore.framework | grep color\]
0x00000e95243 -[UILabel(UILabelDeprecatedMethods) color]

它只是转发给 -textColor:

                     -[UILabel color]:
0000000000e95243         push       rbp                                         ; Objective C Implementation defined at 0x1629e80 (instance method), DATA XREF=0x1629e80
0000000000e95244         mov        rbp, rsp
0000000000e95247         mov        rsi, qword [0x1675228]                      ; argument "selector" for method _objc_msgSend, @selector(textColor)
0000000000e9524e         pop        rbp
0000000000e9524f         jmp        qword [_objc_msgSend_12b96d8]               ; _objc_msgSend, _objc_msgSend_12b96d8,_objc_msgSend

使用相同的方法名称进行两个扩展在 ObjC 中是未定义的行为,你弄错了。

在没有主线程检查器的情况下,或者在发布模式下,我希望您会看到它什么都不做。当主线程检查器注入检查代码时,我预计事情不会完全一致,这会导致崩溃。 (但这都是未定义的行为。很多事情都可能发生。我还没有探索编译器输出以了解到底发生了什么。)

您需要更改此扩展程序的名称。