【问题标题】:Do you have to release IBOulets in dealloc?你必须在 dealloc 中释放 IBoulets 吗?
【发布时间】:2009-10-07 03:37:42
【问题描述】:

你必须在 dealloc 中释放 IBoulet 吗?我不确定这个,因为我没有做分配,通常你只为你调用 alloc 的东西释放。有人知道吗?

【问题讨论】:

标签: iphone


【解决方案1】:

您的 IBOutlets 可能是 @properties。如果是,并且您有retain 作为属性,那么您确实需要在-dealloc 中释放

换句话说:

@interface MyViewController : UIViewController {
    IBOutlet UITableView *myTable;
}

@property (nonatomic, retain) IBOutlet UITableView *myTable;

@end

你必须在你的交易中[myTable release];

如果您在 Xcode 中创建一个新的基于导航的应用程序,并查看 appdelegate.h:

@interface Untitled1AppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;
    UINavigationController *navigationController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

@end

以及 appdelegate.m 的 dealloc:

- (void)dealloc {
    [navigationController release];
    [window release];
    [super dealloc];
}

在这里看到的关键是这样的行:

@property (nonatomic, retain) IBOutlet UIWindow *window;

如果其中有保留,则意味着该属性由您的代码“拥有”,您必须释放它。

当然,还有其他方式,比如不将IBOutlets声明为属性,或者声明为属性而不保留。我发现在大多数情况下,我更喜欢让它们成为保留属性,然后我必须显式释放它们。例如,当您从一个视图控制器切换到另一个视图控制器时。当一个视图控制器被解除时,它的视图被删除并被释放。如果我不保留它们,该视图上的任何 IBOutlet UILabel 也会被释放。这意味着当我翻回旧视图时,我必须重新设置标签和控件到它们的最后值,如果我只保留 IBOutlet,我可以很容易地保存它们。

【讨论】:

    【解决方案2】:

    如果您只是在界面中使用 IBOutlet,则不需要释放它们。原因是除非您在代码中明确保留它们,否则它们只是被设置。他们留下来是因为那里有风景。显然,如果你还使用属性并保留它们,则需要在 dealloc 上释放。

    【讨论】:

    • 这个答案是不是和上面的有冲突?你需要还是不需要?好困惑。
    • 不,这并不冲突:“显然,如果您还使用属性并保留它们,则需要在 dealloc 上释放”。
    • 作为测试,在 Xcode 中制作一个新的基于导航的应用程序。您将看到他们如何在他们的 dealloc 中释放 IBOutlets。
    【解决方案3】:

    这不是关于 IBOutlet,而是关于你的声明。 如果您在 Xcode 中使用新项目向导,您可能会在头文件中得到一些类似这样的代码。

    @property (nonatomic, retain) IBOutlet UIWindow *window;
    @property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
    

    可以看到,头文件中有retain关键字。遵循内存管理指南,您必须释放您保留的所有内容(通过调用 alloc、复制、保留等)。而且您的代码中有retain,那么您必须release它。

    此外,向导已经为您添加了一些发布代码。

    - (void)dealloc {
        [tabBarController release];
        [window release];
        [super dealloc];
    }
    

    【讨论】:

      【解决方案4】:

      正如您所说,您应该释放自己分配的所有内容(使用alloccopy)。它以另一种方式工作:你不应该释放任何不是你自己分配的 Cocoa 对象(一些 CoreFoundation 函数分配,你负责释放它们,但这里不是这种情况)。

      如果您没有分配您的 IBOutlet,那么您不必释放它,当然,除非出于某种原因,您将它保留在某个地方。

      【讨论】:

      • 关键短语是 ("unless.. you reatined it 在某处") 如果你使用 do 属性 (nonatomic,retain) 就会发生这种情况。
      【解决方案5】:

      回答 Joe D'Andrea 的附带问题。您可以使用self.label = nil;。因为它调用的是自动生成的setLabel:

      - (void)setLabel:(UILabel *)input
      {
         [label autorelease];
         label = [input retain];
      }
      

      如您所见,当前的label 将被释放,然后nil 被分配给标签。

      但请确保不要将其写为label = nil。这是行不通的。 因为您需要调用自动生成的标签访问器方法。

      【讨论】:

        【解决方案6】:

        以下是我对 IBOutlet 对象(连同一个 NIB 文件)所做的:

        @interface MyViewController : UIViewController {
          UILabel *label;
        }
        
        @property (nonatomic, retain) IBOutlet UILabel *label;
        
        @end
        
        @implementation MyViewController
        @synthesize label;
        
        - (void)setView:(UIView *)aView {
          if (!aView) {
            // view is being set to nil
            // set outlets to nil to get the benefit of the didReceiveMemoryWarning!
            self.label = nil;
          }
          // Invoke super's implementation last
          [super setView:aView];
        }
        
        - (void)viewDidLoad {
          [super viewDidLoad];
        }
        
        - (void)viewDidUnload {
          // Release any retained subviews of the main view.
          // e.g. self.myOutlet = nil;
          self.label = nil;
        }
        
        - (void)didReceiveMemoryWarning {
          // Releases the view if it doesn't have a superview.
          [super didReceiveMemoryWarning];
        
          // Release any cached data, images, etc that aren't in use.
        }
        
        - (void)dealloc {
          [label release];
          [super dealloc];
        }
        

        附带问题:在 dealloc 中使用 self.label = nil 是否更有意义,还是必须显式调用 release(例如,为了让静态分析器满意)?

        我想,在那一点上,无论如何我们都在退出,所以没有必要将我们的 IBOutlet 对象设置为 nil。

        【讨论】:

          【解决方案7】:

          如果这是你的 BlahViewController.h:

          //  BlahViewController.h
          #import <UIKit/UIKit.h>
          @interface BlahViewController
          {
              IBOutlet UINavigationBar *navigationBar;
          }
          @property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
          
          @end
          

          那么这就是你在 BlahViewController.m 中的dealloc

          - (void)dealloc
          {
              [navigationBar release];
              [super dealloc];
          }
          

          但是,如果这是您的 BlahViewController.h:

          //  BlahViewController.h
          #import <UIKit/UIKit.h>
          @interface BlahViewController
          {
              IBOutlet UINavigationBar *navigationBar;
          }
          
          @end
          

          那么这就是你在 BlahViewController.m 中的dealloc

          - (void)dealloc
          {
              [super dealloc];
          }
          

          最后,如果这是你的 BlahViewController.h:

          //  BlahViewController.h
          #import <UIKit/UIKit.h>
          
          @interface BlahViewController
          {
              IBOutlet UINavigationBar *navigationBar;
              IBOutlet MKMapView *map;
          }
          
          @property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
          
          @end
          

          那么这就是你在 BlahViewController.m 中的dealloc

          - (void)dealloc
          {
              [navigationBar release];
              [super dealloc];
          }
          

          简而言之,如果你把它声明为一个属性,用retain,那么你需要释放它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-06-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-22
            • 2011-03-21
            • 2011-08-30
            • 1970-01-01
            相关资源
            最近更新 更多