Lets say I have a high level class that instantiates an object and then passes it down to a lower level class:
- (void) doSomeStuff {
MyBusinessObject* obj = [[MyBusinessObject alloc] init];
[obj setFoo:@"bar"];
[dataManager takeObj:obj withKey:@"abc" andKey:@"def"];
}
and then in the implementation of takeObj
I want to keep two different dictionaries...
- (void) takeObj:(MyBusinessObject*)obj withKey:(NSString*)key1 andKey:(NSString*)key2 {
[primaryDict setObject:obj forKey:key1];
[secondaryDict setObject:obj forKey:key2];
}
Now, what I want is for the ownership of obj
to be passed down to my data manager and have primaryDict
hold strong references and secondaryDict
hold weak references. This is how I would do it in C++:
map<string, unique_ptr<MyBusinessObject>> primaryDict;
map<string, MyBusinessObject*> secondaryDict;
The takeObj
function would accept a unique_ptr<MyBusinessObject>
that would be passed down with std::move
. That would then be moved again into primaryDict
and a weak reference would be added with a raw pointer in secondaryDict
.
My question is--what is the correct way to tell the Objective-C ARC system to manage my references in that way?
Use NSMapTable, rather than NSDictionary to hold your weak refs. Check the documentation , especially the section on NSMapTableOptions.
You can create a map table with the same behaviour as NSDictionary, but with weak references to the values by initializing with:
[NSMapTable mapTableWithKeyOptions:NSMapTableCopyIn valueOptions:NSMapTableWeakMemory]
This is the Obj-C equivalent of:
std::map<std::string, std::weak_ptr<MyBusinessObject>>
The values won't be retained, and the reference will be automagically set to nil when the object deallocates. The table entry isn't removed though, so you might want to check for entries with nil values and remove them from time to time, depending on how many different keys you're expecting.
Note that there is normally no reason to do this unless you need circular references or are implementing something like a cache. A strong reference is like a std::shared_ptr
in C++, and the convention in Objective-C is to share references to a single object rather than copy/move with a single owner (you'll end up fighting against the language/frameworks if you try to do it differently).
So, the instance with the -takeObj:...
method owns obj
after passing it in? Why does it matter if it does that with two strong references as opposed to one? In short, just use NSMutableDictionary
and let both dictionaries have strong references to obj
. There's not any appreciable performance penalty for this, and the foundation collections don't have built-in support for zeroing weak references, so if that's what you meant by "weak", you would be on your own anyway.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.