假设我有一个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。但是,在委托执行之前,我已经取消了委托,因此它不会执行。现在你怎么解释这个?
答案 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。