What’s the best way to handle memory management with nested factory methods, such as in the following example?
@interface MyClass : NSObject {
int _arg;
}
+ (MyClass *) SpecialCase1;
+ (MyClass *) SpecialCase2;
+ (MyClass *) myClassWithArg:(int)arg;
- (id) initWithArg:(int)arg;
@property (nonatomic, assign) int arg;
@end
@implementation MyClass
@synthesize arg = _arg;
+ (MyClass *) SpecialCase1
{
return [MyClass myClassWithArg:1];
}
+ (MyClass *) SpecialCase2
{
return [MyClass myClassWithArg:2];
}
+ (MyClass *) myClassWithArg:(int)arg
{
MyClass *instance = [[[MyClass alloc] initWithArg:arg] autorelease];
return instance;
}
- (id) initWithArg:(int)arg
{
self = [super init];
if (nil != self) {
self.arg = arg;
}
return self;
}
@end
The problem here (I think) is that the autorelease pool is flushed before the SpecialCaseN methods return to their callers [Edit: apparently not – see comments below]. Hence, the ultimate caller of SpecialCaseN can’t rely on the result having been retained. (I get “[MyClass copyWithZone:]: unrecognized selector sent to instance 0x100110250” on trying to assign the result of [MyClass SpecialCase1] to a property on another object.)
The reason for wanting the SpecialCaseN factory methods is that in my actual project, there are multiple parameters required to initialize the instance and I have a pre-defined list of “model” instances that I’d like to be able to create easily.
I’m sure there’s a better approach than this.
[Edit: @interface added per request.]
The error describes the problem exactly: copyWithZone is called and it’s not implemented in MyClass. Check out the attributes or the implementation of the property it’s assigned to (see if it’s copying). Also, copyWithZone will be called if the instance of MyClass is used as a key to an NSDictionary. Here’s some info on implementing copyWithZone.