The reason for that seems to be that the named:
initializer has a return type of NSImage
class NSImage : NSObject, NSCopying, NSCoding, NSSecureCoding, NSPasteboardReading, NSObjectProtocol, NSPasteboardWriting {
/*All instance variables are private*/
init?(named name: String) -> NSImage /* If this finds & creates the image, only name is saved when archived */
while other (not all) initializers have no return type
init(size aSize: NSSize)
init?(data: NSData) /* When archived, saves contents */
init?(contentsOfFile fileName: String) /* When archived, saves contents */
init?(contentsOfURL url: NSURL) /* When archived, saves contents */
init?(byReferencingFile fileName: String) /* When archived, saves fileName */
init(byReferencingURL url: NSURL) /* When archived, saves url, supports progressive loading */
Now because of that, if you have a class T
that is a subclass of NSImage
you would expect T(named:)
to return an instance of T
but if you do not provide your own implementation, the superclass implementation would be called and as we can see in the declaration, it returns an NSImage
.
Why is it different than all other initializers? I don't know.
Perhaps the underlying implementation and caching mechanisms that NSImage
uses lead to this inconsistency. But what's more important is that the +[NSImage imageNamed:]
does not call any of the NSImage
designated initializers.
Have a look at this example I cooked up witg Cocoa Touch's UIImage
: https://gist.github.com/bartekchlebek/d61154add8525218ae3a
You can see there, that I create a subclass of UIImage
called MyImage
and I override all UIImage
's initializers, place NSLog
s in them and return nil.
In
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
I call -[MyImage imageNamed:]
and notice, that none of the NSLog
's placed in the designated initializers are printed. I also print the class of the instance created with -[MyImage imageNamed:]
and you can see that it is not MyImage
but UIImage
(putting aside the fact that I return nil
in all initializers ;) )
In conclusion, +[UIImage imageNamed:]
does not call any of the UIImage
's designated initializers, thus overriding them will not make +[MyImage imageNamed:]
return an instance of MyImage
. And I expect NSImage
to behave the same way.
This subtlety causes Swift
not to inherit the named:
initializer, because swift requires convenience initializers to go through a designated initializer, while Objective-C did not require that.