简体   繁体   中英

Objective-C ARC pointer ownership vs C++

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM