Without knowing what is the code that is causing the analyzer's behavior it's hard to tell, but as a general rule, here's a couple of compiler-friendly ways to define init/factory methods.
Classic alloc/init
- (instancetype)initWithParameter:(id)parameter {
if(self = [super init]) {
_parameter = parameter;
}
return self;
}
Usage
MyCustomClass * myInstance = [[MyCustomClass alloc] initWithParameter:foo];
This will produce an instance with a +1 retain count. Under ARC this will be automatically managed properly since it follows the NARC rule (New, Alloc, Retain, Copy).
For the same reason, in pre-ARC environments it has to be explicitly released by the client.
Custom factory method
ARC
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
return [[self alloc] initWithParameter:parameter]; // assuming -initWithParameter: defined
}
Pre-ARC
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
return [[[self alloc] initWithParameter:parameter] autorelease]; // assuming -initWithParameter: defined
}
Usage
MyCustomClass * myInstance = [MyCustomClass canIHazInstanceWithParameter:foo];
Both in ARC and pre-ARC the method returns an autoreleased instance (this is clearly more explicit in the pre-ARC implementation), which doesn't have to be managed by the client.
Remarks
You may have noticed the instancetype
keyword. That's a handy language extension introduced by Clang, that turns the compiler into a dear friend when implementing your own constructors/factory methods. I wrote an article on the subject, which may be relevant to you.
Whether factory methods are preferable to init
methods is debatable. From a client perspective it does not make much difference under ARC, provided that you carefully follow the naming conventions, even though I personally tend to expose factory methods in the interface, while implementing custom init
methods only internally (as I did in the examples above). It's more a matter of style than an actual practical concern.