【问题标题】:iOS Memory Management IssueiOS 内存管理问题
【发布时间】:2012-01-29 19:13:56
【问题描述】:

当您使用 Xcode 的功能并从 nib 文件拖到 .h 和 .m 文件中时,Xcode 会在 deallocviewDidUnload 中添加代码。它添加了我通常不添加的额外代码。我只是好奇是否需要这个额外的代码。

我会做[self setDisplaySlider:nil] 而不是disp = nil[disp release]

这有必要吗?我认为您不必释放 disp。

@interface ViewController : UIViewController
{
   IBOutlet UISegmentedControl *disp;    
}

@property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;

@end

- (void)viewDidUnload
{
    [self setDisplaySlider:nil];
    [disp release];
    disp = nil;
    [super viewDidUnload];
}

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

【问题讨论】:

    标签: ios memory-management release-management iboutlet


    【解决方案1】:

    在我看来,您提供了一个带有额外代码的类。我会尽力解释。

    首先,在您的上一个中,您有两个不同的IBOutlet。我想第一个是你加的。

    IBOutlet UISegmentedControl *disp;
    

    第二个是 Xcode 在您进行拖放操作时添加的。

    @property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;
    

    首要考虑

    IBOutlet 一词只是 Xcode 的占位符。通过它,Xcode 可以帮助您将实例变量连接到图形元素。

    当我使用出口连接时,我通常会提供像 @property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider; 这样的访问器(就像 Xcode 所做的那样),因为如果不这样做,您可能会出现内存泄漏问题。

    二次考虑

    Xcode 提供的代码是正确的。当您进行拖动操作时,您将displayController 实例变量与您的图形元素相关联。为了平衡这种连接,必须在 dealloc 方法中释放该实例变量,如下所示:

    [displayController release];
    

    为了成瘾,Xcode 添加了[self setDisplaySlider:nil];,因为在内存警告情况下可以调用viewDidUnload 方法。这里没有问题,因为当控制器再次加载到内存中时,插座连接会恢复。

    两种方法调用的区别可以在Advanced Memory Management docrelease-or-set-to-nil-retained-members中读取。请注意,如果您这样做:

    [displayController release];
    

    您可以直接访问名为displayController 的实例变量,而如果您这样做:

    [self setDisplaySlider:nil]; // or self.displaySlider = nil;
    

    您访问该实例变量的访问器(在本例中为 setter 方法)。不一样(为避免混淆,请参阅我提供的代码)。

    所以,这是我将使用的代码(我添加了一些 cmets 来指导您):

    //.h
    @interface ViewController : UIViewController
    {
        UISegmentedControl *disp; // instance variable called disp
        // (A) now this is no longer necessary, new compile mechanism will create an instance
        // variable called _displaySlider under the hood
    }
    
    @property (retain, nonatomic) IBOutlet UISegmentedControl *displaySlider;
    
    @end
    
    //.m
    @synthesize displaySlider = disp;  // I say to Xcode to create a setter and a getter to access the instance variable called disp as written in @property directive
    // no longer necessary for (A)
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];        
        [self setDisplaySlider:nil]; // I call the setter method to release the UISegmentedControl
    }
    
    - (void)dealloc {
        [disp release]; // I release the UISegmentedControl directly
        // if you choose the (A) mechanism simply do
        // [_displaySlider release];
        [super dealloc];
    }
    

    希望对你有帮助。

    【讨论】:

    • 我明白,XCode 生成的代码似乎与我习惯的不同。即使是没有 @property 的标签,它们也会设置为 nil 并释放。我认为这没有必要
    【解决方案2】:

    看看你的viewDidLoad:,我想你会发现对象正在那里分配。

    您需要在 viewDidUnload 中与释放平衡,否则如果再次加载视图,对象将在没有释放的情况下再次分配,并且您将泄漏。

    【讨论】:

    • 我没有在 viewDidLoad 中分配任何东西,如果你从 Interface Builder 拖放到类文件中,这是 XCode 自动生成的代码
    猜你喜欢
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多