autorelease,函数完成时释放对象

Posted

技术标签:

【中文标题】autorelease,函数完成时释放对象【英文标题】:autorelease, release object when function is finished 【发布时间】:2011-04-04 18:01:24 【问题描述】:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
 
   static NSCharacterSet *charSet = nil;
    if (!charSet) 
        charSet = [[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] retain];
    
    NSRange loc = [(NSString*)textField.text rangeOfCharacterFromSet:charSet];
    if (loc.location != NSNotFound) 
        UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"error!",@"")
                                                             message:@"description."
                                                            delegate:self
                                                   cancelButtonTitle:NSLocalizedString(@"OK",@"")
                                                   otherButtonTitles:nil];
        [errorAlert show];
        [errorAlert release];
        return NO;

    
    return YES;

我有一个与自动释放有关的问题。

我知道当我以这种方式创建对象时:

 charset =[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];

对象是自动释放的。

我有一个问题 - 为什么在这个对象上有一个 retain 的原因是 - 对象在第一次调用函数后被释放?

【问题讨论】:

【参考方案1】:

这是因为 charSet 被声明为静态的。正常范围规则适用,因此它仅在此方法中可见。但是,静态变量存在于堆栈中,并在方法返回时保留它们的值,因此如果再次调用它们,它们仍然具有相同的值。这就是为什么有“if (!charSet)”的原因——它检查对象是否已经创建,所以如果是的话,现有的对象可以被重用。

如果没有 -retain,NSCharacterSet 对象会自动释放,并且它所在的内存块可以(并且将)用于其他用途。但是当发生这种情况时,指向该内存的charSet* 指针不会重置为零。它仍然具有旧值;由于该值非零,if(!charSet) 为假,因此不会创建新对象。但是,由于旧对象已被销毁,因此无法确定该指针所指的内存中可能存在什么 - 它可能是随机垃圾,可能是其他对象,也可能是任何东西。

【讨论】:

好的,我明白了,静态导致该变量在函数完成时不会改变他的值。但是你能再解释一下为什么当我不添加保留时,它不起作用吗? 好的,我扩展了答案的第二部分 - 有帮助吗? 似乎 charSet 在函数完成时被释放,正如你在 charSet 中所说的那样是随机垃圾。我想我明白了,是吗? 次要 nitpick - 只要自动释放池耗尽,就会释放 charSet。这发生在事件处理循环的每次行程结束时,不一定在此方法调用结束时。例如,如果某些东西正在使用 Cocoa Bindings 来观察 textField 的变化,则相关的通知方法也将被调用作为处理此事件的一部分。 嗯,但是你说因为旧对象被破坏了

以上是关于autorelease,函数完成时释放对象的主要内容,如果未能解决你的问题,请参考以下文章

75. Autorelease机制及释放时机

75. Autorelease机制及释放时机

autorelease 对象啥时候释放?

在 Objective-C 中如何处理 Autorelease 池中的对象?

妥善使用autorelease()方法

自动释放对象两次