UserInfo at NSObject level

Guides | Tutorial By 5 years ago

Many times during development I have needed to attach simple user info to objects in Objective-C, such as a table row, context info and other object pointers. Previously to achieve this I would subclass my target object’s class and add the variables needed to hold the extra information. This worked, but had a couple of problems.

Problem 1: The class you want to attach data to must be or derive from the custom subclass you have created. If another class needs to same information, you will also need to subclass that class.

Problem 2: Whenever you want some user info you must create a subclass, which can take a few minutes.

A couple of weekends ago I was looking at the objc_getAssociatedObject and objc_setAssociatedObject methods. These are used to get and set an object that has been attached to a class. They are a little tricky to use, so I have created a wrapper in the form of an NSObject category – meaning with this you can attach user info to ANY object, even if you did not create it.

@interface NSObject (UserInfo)

- (NSMutableDictionary*) objectUserInfo;	//	Any custom information for any object

#import "NSObject+UserInfo.h"


@implementation NSObject (UserInfo)

- (NSMutableDictionary*) objectUserInfo
	static const char* objectUserInfoKey = "objectUserInfoKey";

	NSMutableDictionary* objectUserInfo = objc_getAssociatedObject(self, objectUserInfoKey);

	if(objectUserInfo == nil)
		objectUserInfo = [[NSMutableDictionary alloc] init];
		objc_setAssociatedObject(self, objectUserInfoKey, objectUserInfo, OBJC_ASSOCIATION_RETAIN_NONATOMIC);	//	Retains here, the objc runtime will release it for us on [self dealloc]
		[objectUserInfo release];

	return objectUserInfo;


Calling [obj objectUserInfo]; will return an NSMutableDictionary you can go and add your info too, by value and key. There is no overhead and each object will only be granted an info dictionary when objectUserInfo is first called, so only the objects you want to have info will have info. You do not need to worry about releasing the dictionary, Objective-C automatically handles this when the NSObject is deallocated.

Here is an example of how you can use the method and add/retrieve user info.

NSObject* obj1 = [[NSObject alloc] init];
NSArray* obj2 = [[NSArray alloc] init];

NSLog(@"obj1: %@", [obj1 objectUserInfo]);
[[obj1 objectUserInfo] setValue:@"data" forKey:@"key"];
[[obj1 objectUserInfo] setValue:[NSValue valueWithPointer:self] forKey:@"context"];
NSLog(@"obj1: %@", [obj1 objectUserInfo]);


NSLog(@"obj2: %@", [obj2 objectUserInfo]);
[[obj2 objectUserInfo] setValue:@"data" forKey:@"key"];
NSLog(@"obj2: %@", [obj2 objectUserInfo]);

[obj1 release];
[obj2 release];

The output:

2012-01-03 14:24:53.085 adsdsadas[2698:60b] obj1: {
2012-01-03 14:24:53.086 adsdsadas[2698:60b] obj1: {
    context = "";
    key = data;
2012-01-03 14:24:53.086 adsdsadas[2698:60b] ----
2012-01-03 14:24:53.086 adsdsadas[2698:60b] obj2: {
2012-01-03 14:24:53.087 adsdsadas[2698:60b] obj2: {
    key = data;
  • bob

    You should use [NSValue valueWithNonretainedObject:self] instead of [NSValue valueWithPointer:self]. But why include self in the user info anyway?

    • tom

      Remember that self does not represent obj1, the code above does not store the same object in it’s user info, these are just examples and obviously don’t actually do anything other than demonstrate how it works. I wouldn’t worry about valueWithPointer:, again this is just an example.

      This is intended to hold any data at any object’s level without the need to subclass. A real world example I use for this is attaching processed data to a UIAlertView, then when the alert view’s delegate method is called I can simply extract it from the sender alert view and use it.