将子视图中的委托设置为nil

时间:2011-05-30 05:53:10

标签: iphone objective-c

假设我有一个UIViewController。在UIViewController里面我有一个UITextView。 在viewDidLoad中,我将UITextView的委托设置为self。这意味着我需要在dealloc中执行textview.delegate = nil?这是真的?有人可以用外行语言解释为什么会这样?

如果我误解了“在调用[super dealloc]之前重新启动UIViewController但没有将子视图委托给nil”的概念,那么有人可以给我一个这样的例子

一个错误的例子:(澄清)

CreateGroupViewController * cgvc = [[CreateGroupViewController alloc] init];
    cgvc.delegate = self;
    UINavigationController * uinc = [[UINavigationController alloc] initWithRootViewController:cgvc];
    uinc.navigationBar.tintColor = [UIColor blackColor];
    uinc.modalPresentationStyle = UIModalPresentationFormSheet;
    [self presentModalViewController:uinc animated:YES];
    cgvc.delegate = nil;    
    [cgvc release];

我的观点是,说每次释放一个对象时将委托设置为nil是不对的。在这种情况下,我正在显示ModalViewController。但是,在委托执行之前,我已经取消了委托,因此它不会执行。现在你怎么解释这个?

3 个答案:

答案 0 :(得分:0)

是的,你完成后应该将委托设置为nil。如果尝试在委托对象释放后调用委托对象上的方法,则可以防止应用程序崩溃。 (请记住,向nil对象发送消息是完全合法的。)

Should you set the delegate to nil in the class using the delegate or in the class itself的更多详情。

答案 1 :(得分:0)

是的,这是解决这个问题的正确方法。将委托设置为对象后,实际上是将委托分配给该特定对象,并且在发布之前将其设置为nil的理想方式。

答案 2 :(得分:0)

更新解决您的代码段:

CreateGroupViewController * cgvc;
cgvc = [[CreateGroupViewController alloc] init];
// We now _own_ cgvc; we are responsible for its memory
cgvc.delegate = self;    // cgvc will send us some fun messages

cgvc.delegate = nil;     // Not necessary, because:
[cgvc release];          // cgvc no longer exists

唯一有意义的情况是,如果作为委托的对象(称为A)在委托的对象之前被解除分配,则将其称为{{1 }}。例如,如果B是文本字段,则可能会发生这种情况。 B消失后,文本字段将会停留,我们不希望A尝试向已解除分配的B发送消息:

A

如果变量中有一个对象,并且您不再需要该对象,但该变量可能(意外地)稍后使用,则在释放该对象后将该变量设置为MyDelegateClass * del = [[MyDelegateClass alloc] init]; myLongLivedObjThatNeedsADelegate.delegate = del; // Do stuff... // Release delegate object without setting outlet to nil [del release]; // ---- // Some time later, in myLongLivedObjectThatNeedsADelegate: [delegate objShouldDoX:self]; // CRASH! delegate points to // deallocated instance 是一种安全措施

演示:

nil

当你拥有属性和合成的setter时,它会变得更有趣。如果您有房产:

NSString * str1 = [[NSString alloc] init];
NSString * str2 = [[NSString alloc] init];
NSString * str3 = [[NSString alloc] init];

str1 = nil;       // We just leaked the object that was at str1;
                  // there is no way to release it.
[str1 release];   // Does nothing
[str1 length];    // Also does nothing

[str2 release];   // Release the object
[str2 length];    // CRASH! message sent to deallocated instance

[str3 release];
str3 = nil;      // A safety measure
[str3 length];   // Does nothing

你合成了setter,setter看起来像这样:

@property (retain) NSString * myString;

所以,如果你做- (void) setMyString:(NSString *)newString { [newString retain]; // Take ownership of new object [myString release]; // Relinquish old object myString = newString; // Rename new object } ,会发生什么等同于以下内容:

self.myString = nil;

您会看到合成属性会自动执行传统的“安全”练习。这就是为什么您可能会看到人们建议将属性设置为[self setMyString:nil]; // Inside setMyString: newString is nil [nil release]; // Does nothing [myString release]; // Relinquish old object myString = nil; // Set myString to nil

这里要注意的最后一点是,在nil中将ivar设置为nil并不重要,因为该名称不再被使用。拥有它的对象正在被销毁,因此“安全措施”不适用。因此,在dealloc中,您可以毫无顾虑地释放您的ivars。