问题
Manual memory management is used. The following code runs well and no crash occurs. But there is no -(void)dealloc
method. Is this code wrong? Should I add -(void)dealloc
?
MyClass.h
#import <UIKit/UIKit.h>
@interface MyClass : NSObject {
@private
BOOL flag;
UIView *view;
UILabel *label;
UIButton *button;
UITabBar *tabBar;
UIWebView *webView;
UIImageView *imageView;
}
@property (nonatomic, retain) UIView *view;
@property (nonatomic, retain) UILabel *label;
@property (nonatomic, retain) UIButton *button;
@property (nonatomic, retain) UITabBar *tabBar;
@property (nonatomic, retain) UIWebView *webView;
@end
MyClass.m
#import "MyClass.h"
@implementation MyClass
@synthesize view;
@synthesize label;
@synthesize button;
@synthesize tabBar;
@synthesize webView;
- (id)init {
self = [super init];
if (self) {
// Initialization code
// Among other code,
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
}
return self;
}
// Other methods here.
// But -(void)dealloc is not overridden here in the MyClass.m
@end
If we must add -(void)dealloc
for the above code, should it be like this:
Overridden -(void)dealloc
-(void)dealloc {
[view release];
[label release];
[button release];
[tabBar release];
[webView release];
[super dealloc];
}
Update 1
@synthesize added, see above.
Update 2
Didn't put this into another post because this seems rather related issue:
See the above MyClass.m/.h
, there is a private ivar (not sure it should be called ivar or field here) UIImageView *imageView;
, it has no property for it, no @synthesize
, initialization given there, how can we dealloc it? Also [imageView release];
in -(void)dealloc
?
Update 3
Do we have to check availability before releasing ivars? That is, instead of [view release];
, use this:
if (nil != view) {
[view release];
}
回答1:
Yes. You need to implement dealloc.
You dealloc will look like :
-(void)dealloc {
[_view release];
[_label release];
[_button release];
[_tabBar release];
[_webView release];
[super dealloc];
}
Any retained/copy property should be released on dealloc.
Your iVar have no meaning. They do not have the same information as the properties, so you can remove your iVars.
If you want your properties to be backed up by your iVars you should @synthesize
them like:
@synthesize view = view;
@synthesize label = label;
@synthesize button = button;
@synthesize tabBar = tabBar;
@synthesize webView = webView;
回答2:
As you are not using ARC, your code (including the dealloc method) is correct, however you are missing the @synthesize statement in the implementation for the properties to work:
@implementation MyClass
// this will synthesize the getters and setters
@synthesize view, label, button, tabBar, webView;
- (id)init {
self = [super init];
if (self) {
// Initialization code
}
return self;
}
// Other methods here.
-(void)dealloc {
[view release];
[label release];
[button release];
[tabBar release];
[webView release];
[super dealloc];
}
@end
回答3:
While Daniel's answer is correct in addressing your question, it does not cover what you should do.
This is how your code would be written in a modern world:
turn on ARC. Especially if you are learning or this is your first project. There is no reason to not use ARC. Learning manual-retain-release is valuable, but not critical at this time as the tools do a very good job of providing analysis of when ARC based patterns are leaking memory (either the analyzer or using Instruments, both of which you would need to use under MRR and neither of which work as well under MRR).
Don't use @synthesize and don't declare iVars (and certainly don't declare iVars in your .h file). Let the compiler autho-synthesize the
_
prefixed ivars automatically. The_
prefix has the added advantage of disallowing you from accidentally directly accessing an ivar in code. I.e.self.foo
vs.foo
; the second won't compile.
Or to translate into code:
@interface MyClass : NSObject
@property (nonatomic, retain) UIView *view;
@property (nonatomic, retain) UILabel *label;
@property (nonatomic, retain) UIButton *button;
@property (nonatomic, retain) UITabBar *tabBar;
@property (nonatomic, retain) UIWebView *webView;
@end
And:
@implementation MyClass
{
BOOL _flag;
UIImageView *_imageView;
}
- (id)init {
self = [super init];
if (self) {
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
}
return self;
}
// no -dealloc
@end
Note that I declared _imageView
as an instance variable that will be compatible with the obvious imageView
@property
should you need to refactor your class later to make that externally available.
If you realy must use manual retain-release, then add a -dealloc
method that calls -release
on all the ivars. I.e.[_view release];
, [_imageView release];
, etc...
Don't get what you mean by "Note that I declared _imageView as an instance variable that will be compatible with the obvious imageView @property should you need to refactor your class later to make that externally available."
If you were to decide that _imageView
needs to be accessible to other objects, then you would delete the iVar declaration and add:
@property(nonatomic, retain) UIImageView *imageView;
The compilers automatic synthesis would create an instance variable named _imageView
automatically and none of the rest of your code would have to change.
Do we have to make sure an ivar is not nil before releasing it in dealloc method? (See Update 3 above.)
No. In Objective-C, nil eats messages. That is, [nil release];
is perfectly valid and does absolutely nothing at runtime.
In your code the BOOL flag; has disappeared. Do we have make a property for BOOL flag;, that is, @property BOOL flag;? Or all we have to do is just placing a private field in the MyClass.h as @private BOOL flag; up there in my original question?
I forgot it. You could create a property for it. Or you could declare _flag
as an iVar next to _imageView
as I've done above.
Most importantly, there is no longer any reason (save for a very rare case that is generally too be avoided) to declare instance variables in your .h.
来源:https://stackoverflow.com/questions/19653399/can-this-code-works-without-overridden-dealloc-method-objective-c