什么是 objc_setAssociatedObject() 以及在什么情况下应该使用它?
在我承担的一个项目中,原作者选择使用 objc_setAssociatedObject(),但我并不 100% 清楚它的作用或他们决定使用它的原因。
我决定查找它,不幸的是,文档并没有很好地描述其用途。
objc_setAssociatedObject
使用给定键和关联策略为给定对象设置关联值。void objc_setAssociatedObject(id 对象, void *key, id 值, objc_AssociationPolicy 策略)
参数对象
关联的源对象。密钥
协会的钥匙。值
与对象的键关联的值。传递 nil 来清除现有关联。政策
协会的政策。有关可能的值,请参阅“关联对象行为”。
那么这个函数到底有什么作用以及在什么情况下应该使用它呢?
阅读答案后进行编辑
那么下面的代码有什么意义呢?
Device *device = [self.list objectAtIndex:[indexPath row]];
DeviceViewController *next = [[DeviceViewController alloc] initWithController:self.controller
device:device
item:self.rootVC.selectedItem];
objc_setAssociatedObject(device, &kDeviceControllerKey, next, OBJC_ASSOCIATION_RETAIN);
如果设备已经是实例变量,那么将设备与视图控制器关联起来有什么意义呢?
In a project I have taken on, the original author has opted to use objc_setAssociatedObject()
and I'm not 100% clear what it does or why they decided to use it.
I decided to look it up and, unfortunately, the docs aren't very descriptive about its purpose.
objc_setAssociatedObject
Sets an associated value for a given object using a given key and association policy.void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)
Parametersobject
The source object for the association.key
The key for the association.value
The value to associate with the key key for object. Pass nil to clear an existing association.policy
The policy for the association. For possible values, see “Associative Object Behaviors.”
So what exactly does this function do and in what cases should it be used?
Edit after reading answers
So what is the point in the following code?
Device *device = [self.list objectAtIndex:[indexPath row]];
DeviceViewController *next = [[DeviceViewController alloc] initWithController:self.controller
device:device
item:self.rootVC.selectedItem];
objc_setAssociatedObject(device, &kDeviceControllerKey, next, OBJC_ASSOCIATION_RETAIN);
What is the point in associating the device with the view controller if it's already an instance variable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
objc_setAssociatedObject
向每个 Objective-C 对象添加一个键值存储。它允许您存储对象的附加状态,而不是反映在其实例变量中。当您想要存储属于主实现之外的对象的内容时,这确实很方便。主要用例之一是无法添加实例变量的类别。在这里,您使用 objc_setAssociatedObject 将附加变量附加到 self 对象。
当使用正确的关联策略时,当主对象被释放时,您的对象将被释放。
objc_setAssociatedObject
adds a key value store to each Objective-C object. It lets you store additional state for the object, not reflected in its instance variables.It's really convenient when you want to store things belonging to an object outside of the main implementation. One of the main use cases is in categories where you cannot add instance variables. Here you use
objc_setAssociatedObject
to attach your additional variables to theself
object.When using the right association policy your objects will be released when the main object is deallocated.
来自 目标的参考文档-C 运行时参考:
建立数组和字符串之间的关联
From the reference documents on Objective-C Runtime Reference:
Establishing an association between an array and a string
以下是对象关联的用例列表:
一个: 将实例变量添加到类别。一般来说,不建议使用这种技术,但这里有一个合法使用的示例。假设您想要为无法修改的对象模拟附加实例变量(我们正在讨论修改对象本身,即没有子类化)。假设在 UIImage 上设置标题。
另外,这里是一种使用类别关联对象的非常复杂(但很棒)的方法..它基本上允许您通过在块中而不是
UIControl
的选择器中。二:结合KVO动态地给未被其实例变量覆盖的对象添加状态信息。
这个想法是你的对象仅在运行时(即动态地)获取状态信息。因此,我们的想法是,虽然您可以将此状态信息存储在实例变量中,但事实上,您将此信息附加到在运行时实例化的对象中并将其与另一个对象动态关联,您强调了这样一个事实:物体的动态状态。
说明这一点的一个很好的例子是这个库,其中关联对象与 KVO 通知一起使用。以下是代码摘录(注意:运行该 KVO 通知并不是使该库中的代码正常工作所必需的。相反,它是作者为了方便起见而放在那里的,基本上任何注册到此的对象都将通过 KVO 收到通知发生了变化):
奖励:看看这个讨论/解释< /a> 关联对象,作者:Mattt Thompson,开创性 AFNetworking 库的作者
Here is a list of use cases for object associations:
one: To add instance variables to categories. In general this technique is advised against, but here is an example of a legitimate use. Let's say you want to simulate additional instance variables for objects you cannot modify (we are talking about modifying the object itself, ie without subclassing). Let's say setting a title on a UIImage.
Also, here is a pretty complex (but awesome) way of using associated objects with categories.. it basically allows you to pass in a block instead of a selector to a
UIControl
.two: Dynamically adding state information to an object not covered by its instance variables in conjunction with KVO.
The idea is that your object gains state information only during runtime (ie dynamically). So the idea is that although you can store this state info in an instance variable, the fact that you're attaching this info into a an object instantiated at runtime and dynamically associating it with the other object, you are highlighting the fact that this is a dynamic state of the object.
One excellent example that illustrates this is this library, in which associative objects are used with KVO notifications. Here is an excerpt of the code (note: this KVO notification isn't necessary to run make the code in that library work.. rather it's put there by the author for convenience, basically any object that registers to this will be notified via KVO that changes have happened to it):
bonus: take a look at this discussion/explanation of associated objects by Mattt Thompson, author of the seminal AFNetworking library
回答您修改后的问题:
您可能想要这样做的原因有多种。
就我个人而言,我认为很少需要使用低级 Objective-C 运行时函数。对我来说这看起来像是代码味道。
To answer your revised question:
There are several reasons why you might want to do this.
Personally, I think it is very rare to need to use low level Objective-C runtime functions. This looks like a code smell to me.