Chris Chris -4 years ago 115
Objective-C Question

Objective-C class method local variables of type "self"

We're all familiar with the following pattern for instantiating instances of a class:

+ (instancetype)createInstance {
return [[self alloc] init];
}


This works because "self" in this case refers to the class rather than an object built from the class blueprint.

We also know this declaration, most commonly used in avoiding retain cycles:

typeof(self) someStrongSelf = self;


This is allows
self
's type to be dynamic and that code could be copy-pasted wherever needed no matter the class.

My question deals with combining the above two patterns when instantiating from a class method:

+ (instancetype)createInstance:(MyObject*)dependency {
typeof(self) instance = [[self alloc] init];
instance.dependency = dependency;

return instance;
}


This won't work because
self
is a class, and a
typeof(class)
is just a
Class
, but is there some mechanism for local variables equivalent to
instancetype
that would allow me the same flexibility as typeof(instance)? For example:

+ (instancetype)createInstance:(MyObject*)dependency {
instanceof(self) instance = [[self alloc] init]; //desired keyword
instance.dependency = dependency;

return instance;
}


If I really wanted this formalized, I know an alternative to this would be defining a protocol that does basically the same thing as above, but I'm curious if Objective-C allows the desired declaration style out of the box.

Answer Source

I understand what you're looking for, but there is no instanceof(self) pattern. The following achieves what you want, though admittedly doesn't have the elegance of typeof(self) pattern:

@interface Foo: NSObject
@property (nonatomic, copy) NSString *string;
@end

@implementation Foo
+ (instancetype)fooWithString:(NSString *)string {
    Foo *foo = [[self alloc] init];
    foo.string = string;
    return foo;
}
@end

@interface Foobar: Foo
// perhaps some more properties here
@end

@implementation Foobar
// and perhaps some more methods here
@end

This implementation demonstrates that the convenience method still allows subclassing. I.e., you can do:

Foobar *foobar = [Foobar fooWithString:@"baz"];

And the resulting object will be a Foobar instance.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download