Can this code works without overridden dealloc method (Objective-C)

假如想象 提交于 2019-12-24 19:09:02

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!