0

我正在编写一个 iPhone 应用程序,并且在我的一种方法中遇到了关于内存管理的问题。我对手动管理内存还有些陌生,所以如果这个问题看起来很简单,我很抱歉。

下面是一种旨在允许数字键盘根据其标签将按钮放置在标签中的方法,这样我就不需要为每个按钮创建一个方法。该方法工作正常,我只是想知道我是否负责释放我在函数中创建的任何变量。

如果我尝试释放任何变量,应用程序就会崩溃,所以我对我在内存方面的责任感到有点困惑。

这是方法:

仅供参考,变量 firstValue 是我的标签,它是方法中唯一未声明的变量。

-(IBAction)inputNumbersFromButtons:(id)sender {
    UIButton *placeHolderButton = [[UIButton alloc] init];
    placeHolderButton = sender;

    NSString *placeHolderString = [[NSString alloc] init];
    placeHolderString = [placeHolderString stringByAppendingString:firstValue.text];

    NSString *addThisNumber = [[NSString alloc] init];
    int i = placeHolderButton.tag;

    addThisNumber = [NSString stringWithFormat:@"%i", i];

    NSString *newLabelText = [[NSString alloc] init];
    newLabelText = [placeHolderString stringByAppendingString:addThisNumber];

    [firstValue setText:newLabelText];

    //[placeHolderButton release];
    //[placeHolderString release];
    //[addThisNumber release];
    //[newLabelText release];

}

该应用程序在最后四行被注释掉的情况下运行良好,但在我看来,我应该在这里发布这些变量。如果我错了,我欢迎快速解释一下何时需要释放函数中声明的变量以及何时不需要。谢谢。

4

4 回答 4

3

是的,你需要释放它们,但你需要它们的时间比你的函数结束的时间长一点。

解决方案称为autorelease。只需替换releaseautorelease,对象就会一直存在,直到程序返回运行循环。

当程序回到那里时,每个对其中一个对象感兴趣的人都应该retain向它发送消息,因此该对象在被释放时不会被释放NSAutoreleasePool

实际上进行编辑,查看您的代码,它还有很多错误。例如这个:

UIButton *placeHolderButton = [[UIButton alloc] init];
placeHolderButton = sender;

没有意义。首先你分配一个对象,然后将它分配(一个指针)给 variable placeHolderButton。没关系。

然后你分配sender给同一个变量。对您刚刚创建的对象的引用现在丢失了。

不知道我是否得到你想要的,但这会更好:

-(IBAction)inputNumbersFromButtons:(id)sender {
    UIButton *placeHolderButton = sender; // this is still a little useless, but ok

    int i = placeHolderButton.tag;
    NSString *addThisNumber = [NSString stringWithFormat:@"%i", i];

    NSString *placeHolderString = firstValue.text;

    NSString *newLabelText = [placeHolderString stringByAppendingString:addThisNumber];

    [firstValue setText:newLabelText];
}

没有分配,所以不需要释放。这些函数返回的字符串已经添加到自动释放池中,因此它们将被自动释放(如果需要)。

于 2011-01-06T23:25:01.353 回答
0

好。完成后释放它们。越早越好。如果您不熟悉内存管理,有些对象会很棘手。

然后在 dealloc 方法中释放它们。

自动释放池可以很方便,有些人可能会根据性能问题不同意。

于 2011-01-06T23:26:35.927 回答
0

你需要释放任何包含单词 new、alloc/init 或 copy 的东西。

此外,您不需要分配/初始化这个:

UIButton *placeHolderButton = [[UIButton alloc] init];
placeHolderButton = sender;

另一种方法是:

UIButton *placeHolderButton = (UIButton *)sender;

在您的版本中,它正在分配一个保留计数为 +1 的实例,但您会立即替换引用,因此以后无法释放内存。

您正在使用 alloc/init 创建很多实例,然后用自动释放的实例替换它们的引用。

你可以使用

    NSString *placeHolderString = [placeHolderString stringByAppendingString:firstValue.text];

代替

 NSString *placeHolderString = [[NSString alloc] init];
placeHolderString = [placeHolderString stringByAppendingString:firstValue.text];

这再次将第一行创建的手动管理实例替换为第二行的自动发布实例。

事实上,您可以用工厂方法替换其中的每个 alloc/init,而不必处理其中的内存,因为它们将是自动释放的实例。

-(IBAction)inputNumbersFromButtons:(id)sender {
    //cast sender as a UIButton to suppress compiler warning, and allow us to reference it as placeholder button
    UIButton *placeHolderButton = (UIButton *) sender;

    int i = placeHolderButton.tag;

    NSString *addThisNumber = [NSString stringWithFormat:@"%i", i];
    [firstValue setText:[firstValue.text stringByAppendingString:addThisNumber]];
}

如果您查看 NSString 的类文档,任何带有 + 的方法(即 +stringWithString:(NSString *)string)都是类方法,在调用 alloc/init 后不要在引用上使用这些方法在上面。

于 2011-01-06T23:44:09.047 回答
0

我发现您在 UIButton 上使用 alloc/init 令人费解。

我总是使用工厂方法,例如

UIButton* aButton = [UIButton buttonWithType:UIButtonTypeCustom];

这将返回一个自动释放的按钮,我立即将其添加到其预期的父视图中。

目前无法确认,但看起来 SDK 缓存了 UIButton 实例并在幕后执行了一些优化。每次我尝试保留 UIButton ivar 时,性能都会下降(尤其是当屏幕上有很多子视图时)

于 2011-10-24T07:08:20.607 回答