I have recently learned about associated objects in objective-c and how to implement them. From my understanding, they are helpful if you have a property that you want only a single instance of an object to have.
I can't think of any specific use cases for associated objects in objective-c (meaning use cases that I can't do using some other means).
Does anyone have specific examples of when to use associated objects?
You can use associated objects to add block handlers to classes that don't currently include them. For example, you can add block handling to
UIButton
so that instead of usingaddTarget:action:forControlEvents:
, you could haveaddBlockHandler:forControlEvents:
that takes a block to execute instead. I've also used this to add block handling toUIAlertView
in place of using a delegate.You can use a similar pattern to add block handling to pretty much any class that currently uses a delegate or dataSource.
It is useful when Apple has designed a class incorrectly, such that you can't subclass it.
A good example is NSURLSessionDownloadTask. Let's suppose that when you create the task you want to attach a piece of data to it, to be retrieved when the final task delegate message arrives.
But you can't subclass NSURLSessionDownloadTask; you have to accept the task that NSURLSession gives you. So you can't attach any data to it by normal means. One solution in this situation is an associated object.
Personally I wish every object behaved like CALayer and CAAnimation, where you can attach as much data to it as you like in the form of key-value pairs, as if the object were secondarily a kind of NSDictionary.
There are several situations when using an associated object is possible. Sometimes they are used when for some reason the object cannot be subclassed. However, there are more interesting scenarios:
If the class of the object is unknown. For example, when you want to associate data with some black box objects. Imagine you are creating a new container class (a linked list) and you want to associate some data with every object added to the container.
You want to add a property using a category. Normally, only methods can be added with a category. Using associated objects you can create categories that can store additional data.
The common use case for an associated object is when you need to attach your own data to some object but you can't modify the class or create a subclass, either because it's not designed for subclassing or because you have no control over how the object is created. This is also a common reason to create a category, so it's common to use associated objects in a category.
For example, suppose you want to create a drawing app that supports drawing with multiple touches simultaneously. You want each touch to create an independent curve on the screen. It would be nice if you could add two properties to each touch: a
path
property (for constructing the curve as the touch moves) and ashapeLayer
property (for displaying the curve on the screen).But you have no control over the creation of
UITouch
objects. UIKit creates eachUITouch
object without any hook for you to use a subclass that adds your properties.Instead, you can create a category on
UITouch
that adds your properties:UITouch+Rob_Sketch.h
UITouch+Rob_Sketch.m
Then, in your controller, you can use the category to access the path and shape layer of each touch: