![](/img/trans.png)
[英]Any gotchas with objc_setAssociatedObject and objc_getAssociatedObject?
[英]`objc_setAssociatedObject` and `objc_getAssociatedObject` isn't match
我只想像这样向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];
.
我在 Bugly 中崩溃是这个NSInvalidArgumentException -[_UILabelStringContent doubleValue]: unrecognized selector sent to instance 0x2804fb280
。
那么为什么会发生这种情况。 我只是设置了一个float value
但得到了一个_UILabelStringContent value
。
PS:我的项目是 swift 5.0,但我只是使用 Objective-C 运行时来添加额外的属性。
PS2:我在另一个Objective-C项目中使用了相同的代码,它不会崩溃。
PS3:它并不总是崩溃。
PS4:我在UIView
和BaseLabel
使用了 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
支持对象,该对象保存@(maxWidth)
缩短语法所隐含的CGFloat
值。 由于NSNumber
是NSObject
的子类,因此您不应该使用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 语法角度)传递。 除非方法调用以某种方式格式错误,否则访问它不是崩溃的可能原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.