Reputation: 307
I currently have some code that looks like:
-(UIView)someMethod {
CGRectMake(0,0,100,100);
UILabel *label = [[UILabel alloc] initWithFrame:rect];
return label;
}
While it works it obviously leaks memory and needs to be fixed. I thought the fix would be:
UILabel *label = [UILabel initWithFrame:rect];
But the compiler tells me that UILabel doesn't respond to initWithFrame. I guess my question is two-fold:
a) What is the correct way to do this so I'm not leaking memory?
and
b) I'm confused as to why [UILabel alloc] would respond to initWithFrame but not UILabel by itself (my understanding is that UILabel is inherited from UIView that does respond to initWithFrame).
Upvotes: 1
Views: 2161
Reputation: 104698
a)
-(UIView *)someMethod {
return [[[UILabel alloc] initWithFrame:CGRectMake(0,0,100,100)] autorelease];
}
b) you're misunderstanding the difference between a class method and an instance method.
a class method is declared and used like so:
// declaration: notated with +
+ (NSDocumentController *)sharedDocumentController;
// usage
NSDocumentController * thang = [NSDocumentController sharedDocumentController];
a instance method is declared and used like so:
// declaration: notated with -
- (id)init;
// usage:
// + alloc is a class method
// this requests the class (NSObject) to allocate and return a newly allocated NSObject
// - init is the instance method
// this sends a message to the NSObject instance (returned by [NSObject alloc])
NSObject * thang = [[NSObject alloc] init];
in your example, alloc
returns an allocated instance, which you are then expected to call an appropriate init instance method on.
some classes provide convenience constructors, which often return an autoreleased instance:
+ (NSNumber *)numberWithInt:(int)anInt;
but it is not terribly common to duplicate code in this manner, unless you're working with advanced topics such as class clusters. of course, it may be a good idea to add this to the interface if you find you regularly need a particular functionality or convenience constructor.
Upvotes: 1
Reputation: 9698
Just use your original method and use
return [label autorelease];
instead.
Upvotes: 0
Reputation: 2992
Maybe more like:
-(UILabel)someMethod {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,100,100)];
return [label autorelease];
}
Upvotes: 2
Reputation: 523214
a) You can't avoid +alloc
. But you can use -autorelease
to relinquish the ownership.
-(UIView*)someMethod {
CGRect rect = CGRectMake(0,0,100,100);
UILabel *label = [[[UILabel alloc] initWithFrame:rect] autorelease];
return label;
}
b) +alloc
is a class method, and -initWithFrame:
is an instance method. The latter can only be called on (or, in ObjC terminology, sent to) an instance of UILabel. However, the symbol "UILabel" is a class, not an instance, so [UILabel initWithFrame:rect]
won't work. Similarly, a class method like +alloc
can only be called on a class, so [label alloc]
won't work.
Upvotes: 4