What is the new self-reference reference self-release template?

Using the NSObject -(id)awakeAfterUsingCoder:(NSCoder *)decoder method as an example, the documentation says:

Allows an object after decoding to replace another object for itself. For example, an object representing a font can be decoded, freed, and return an existing object that has the same font description as it is. Thus, redundant objects can be eliminated.

Usually you did

 [self release]; return substitutedObject; 

With ARC, you must exit this line. Would this leak be? Or should I just trust the NSCoder object to free the source object for me? If so, why should you explicitly free yourself with code other than ARC in the first place?

I don't think self = nil true in light of what the compiler documentation says about itself: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#misc.self

+7
source share
3 answers

As already noted, you cannot write [self release]; . In addition, awakeAfterUsingCoder: not an initializer - you cannot reassign self .

Would this leak be?

Yes. Proved in the program below.

Or do I just need to trust the NSCoder object to free the source object for me?

Not.

One way to avoid the leak exists below - I would not call it a โ€œnew templateโ€, namely the first approach that came to mind. It includes an explicit self release and in this case an explicit save result:

 #import <Foundation/Foundation.h> @interface MONBoolean : NSObject < NSCoding > - (id)initWithBool:(bool)pBool; - (bool)isTrue; - (bool)isFalse; @end static NSString * const MONBoolean_KEY_value = @"MONBoolean_KEY_value"; @implementation MONBoolean { bool value; } - (id)initWithBool:(bool)pBool { self = [super init]; if (0 != self) { value = pBool; } return self; } - (bool)isTrue { return true == value; } - (bool)isFalse { return false == value; } - (NSString *)description { return [[NSString alloc] initWithFormat:@"<%s:%p> : %s", object_getClassName(self), self, self.isTrue ? "true" : "false"]; } - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeBool:value forKey:MONBoolean_KEY_value]; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (0 != self) { value = [aDecoder decodeBoolForKey:MONBoolean_KEY_value]; } return self; } - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder { const bool b = value; // cannot reassign self outside of an initializer. // if not released, will result in a leak: CFRelease((__bridge const void*)self); MONBoolean * result = [[MONBoolean alloc] initWithBool:b]; // now we have to retain explicitly because this is // an autoreleasing method: CFRetain((__bridge const void*)result); return result; } @end int main(int argc, const char * argv[]) { @autoreleasepool { MONBoolean * a = [[MONBoolean alloc] initWithBool:true]; NSData * data = [NSKeyedArchiver archivedDataWithRootObject:a]; MONBoolean * b = [NSKeyedUnarchiver unarchiveObjectWithData:data]; NSLog(@"%@", b); } system("leaks NAME_OF_PROCESS_HERE"); return 0; } 
+2
source

A similar problem occurs in the context of top-level NIB objects in Mac OS X. The Resource Programming Guide says:

If the file owner is not an instance of NSWindowController or NSViewController , you need to decrease the reference counter for top-level objects yourself. Using manual reference counting, it was possible to achieve this by sending top-level objects a release . You cannot do this with ARC. Instead, you add references to top-level objects of type Core Foundation and use CFRelease .

Thus, this technique can also be used in this situation. CFRelease((__bridge CFTypeRef)self);

+4
source

I believe ARC is smart enough to track all objects. Thus, you should be able to say nothing about memory, and the application will free the object when it is no longer in use. Run it through the leak profiler, just in case, but everything should be in order.

0
source

All Articles