我只想像这样向UIView添加一个属性,

#import "UIView+Extension.h"
#import <objc/runtime.h>

@implementation UIView (Extension)

- (void)setMaxWidth:(CGFloat)maxWidth {
    objc_setAssociatedObject(self, @selector(maxWidth), @(maxWidth), OBJC_ASSOCIATION_ASSIGN);
}

- (CGFloat)maxWidth {
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

@end

但有时有用,有时会崩溃。

我在XCode中获得崩溃信息是此行return [objc_getAssociatedObject(self, _cmd) doubleValue];

ios - ʻobjc_setAssociatedObject`和 `objc_getAssociatedObject`不匹配-LMLPHP

我在Bugly中崩溃是这个NSInvalidArgumentException -[_UILabelStringContent doubleValue]: unrecognized selector sent to instance 0x2804fb280

ios - ʻobjc_setAssociatedObject`和 `objc_getAssociatedObject`不匹配-LMLPHP

那么为什么会这样。我只是设置了一个float value但得到了_UILabelStringContent value

PS:我的项目使用的是Swift 5.0,但是我只是使用Objective-C运行时来添加额外的属性。

PS2:我在另一个Objective-C项目中使用了相同的代码,它不会崩溃。

PS3:它并不总是崩溃。

PS4:我在UIViewBaseLabel中使用了this属性,但在BaseLabel中仅崩溃了。

PS5:我用它来更新框架,像这样在BaseLabel中使用它。
override func sizeToFit() {
        super.sizeToFit()
        if self.maxWidth > 0 {
            if numberOfLines != 1 {
                let size = self.sizeThatFits(CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude))
                self.size = size
            } else {
                if self.size.width > maxWidth {
                    self.size.width = maxWidth
                }
            }
        }
    }

PS6:是通过_cmd中的objc_getAssociatedObject(self, _cmd)进行崩溃调用吗?

最佳答案

- (void)setMaxWidth:(CGFloat)maxWidth内部,您要创建 NSNumber后备对象,该对象保存CGFloat缩短语法所隐含的@(maxWidth)值。由于NSNumberNSObject的子类,因此您不应该使用OBJC_ASSOCIATION_ASSIGN,它对于具有ARC处理的引用计数的类型无效(对于诸如Integer的值类型有效)。您应该改为使用OBJC_ASSOCIATION_RETAIN
将您的代码更新为

- (void)setMaxWidth:(CGFloat)maxWidth {
        objc_setAssociatedObject(self, @selector(maxWidth), @(maxWidth), OBJC_ASSOCIATION_RETAIN);
}

关于PS6部分,_cmd是给定Objective-C方法主体中的选择器名称(内部表示为char*)。对于每个通过选择器的方法调用,它作为“隐藏”参数(从obj-c语法角度)传递。除非方法调用的格式有误,否则访问它不太可能导致崩溃。

关于ios - ʻobjc_setAssociatedObject`和 `objc_getAssociatedObject`不匹配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59014089/

10-10 13:44