I want to force user to use my own init method (for example -(id)initWithString:(NSString*)foo;
) and not the basic [[myObject alloc]init];
.
how can I do that?
While it is easy to just crash at runtime when somebody calls your method, compile-time checking would be far preferable.
Fortunately, this has been possible in Objective-C for a while.
Using LLVM, you can declare any method as unavailable in a class like so
- (void)aMethod __attribute__((unavailable("This method is not available")));
This will make the compiler complain when trying to call aMethod
. Great!
Since - (id)init
is just an ordinary method, you can prohibit calling of the default (or any other) initializer in this way.
Note, though, that this will not insure against the method being called using the dynamic aspects of the language, for instance via [object performSelector:@selector(aMethod)]
etc. In the case of init, you won't even get a warning, because the init method is defined in other classes, and the compiler doesn't know enough to give you an undeclared selector warning.
So, to ensure against this, make sure that the init method crashes when being called (see Adam's answer).
If you want to disallow - (id)init
in a framework, make sure to also disallow + (id)new
, as this will just forward to init.
Javi Soto has written a small macro to forbid using the designated initializer faster and easier and to give nicer messages. You can find it here.
tl; dr
Swift:
private init() {}
Since all Swift classes include an internal init by default, you can change it to private to keep other classes from calling it.
Objective C:
Put this in your class's .h file.
- (instancetype)init NS_UNAVAILABLE;
This relies on an OS define that prevents the method named from being called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With