我的程序崩溃了,因为我的TextField在代理被释放后向其委托发送消息。我有一个对象,作为UITableViewDataSource和UITextFieldDelegate。在cellForRowAtIndexPath中,我在每个TableViewCell中创建一个TextField,并将self指定为TextField的委托。当我单击屏幕上的一个按钮时,视图会重新加载(它运行的是第一次加载视图时运行的所有相同代码):
DetailsViewController *controller = [[DetailsViewController alloc] initWithNibName:@"ClientView" bundle:nil];
self.detailsViewController = controller;
[controller release];
NRFCAppDelegate *appDelegate = UIApplication.sharedApplication.delegate;
for (UIView *view in [[[appDelegate.splitViewController.viewControllers objectAtIndex:1] view] subviews])
{
[view removeFromSuperview];
}
CGRect rect = [[[appDelegate.splitViewController.viewControllers objectAtIndex:1] view] frame];
self.detailsViewController.view.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
[[[appDelegate.splitViewController.viewControllers objectAtIndex:1] view] addSubview:self.detailsViewController.view];
self.detailsViewController.detailsTitle.title = self.currentClient.name;
self.menuViewController.clientLabel.text = self.currentClient.name;
self.menuViewController.propertyLabel.text = @"Properties:";
self.menuViewController.addPropertyButton.hidden = NO;
self.menuViewController.editPropertiesButton.hidden = NO;
ClientMenuDelegate *menuDelegate = [[ClientMenuDelegate alloc] initWithRootController:self];
menuDelegate.properties = self.currentClient.properties.allObjects;
self.menuViewController.tableView.delegate = self.menuViewController.tableView.dataSource = menuDelegate;
self.menuViewController.delegate = menuDelegate;
[menuDelegate release];
ClientDetailsDelegate *detailsDelegate = [[ClientDetailsDelegate alloc] initWithRootController:self];
detailsDelegate.client = self.currentClient;
self.detailsViewController.tableView.delegate = self.detailsViewController.tableView.dataSource = detailsDelegate;
self.detailsViewController.detailsDelegate = detailsDelegate;
[detailsDelegate release];
[self.menuViewController.tableView reloadData];
[self.detailsViewController.tableView reloadData];
self.detailsViewController.detailsDelegate = detailsDelegate;
导致先前的ClientDetailsDelegate被释放(因此被释放),因为它是一个retain-type属性。问题是,如果我的TextField在单击重新加载按钮时是FirstResponder,它仍然会将它的textFieldShouldEndEditing,textFieldEditorDidChangeSelection等消息发送到现在解除分配的ClientDetailsDelegate。看起来这些消息应该在执行上述任何代码之前发送,因为TextField在单击按钮时失去焦点。此外,一旦调用了removeFromSuperview,TextField本身就不再存在了。
如何在重新加载视图时确保TextField被销毁,并在委托被解除分配后阻止它向其委托发送消息?
答案 0 :(得分:0)
文本字段仅在所有这些内容发生后才发送这些消息,因为当前控件可能拒绝接受第一响应者。无论如何,原因并不重要。关键是你在使用它的控件完成之前就要销毁一个委托。行前:
self.detailsViewController.detailsDelegate = detailsDelegate;
您需要将旧委托所使用的控件的delegate
属性设置为nil。您可以在委托对象的dealloc方法中执行此操作。
另一方面说明:
ClientMenuDelegate *menuDelegate = [[ClientMenuDelegate alloc] initWithRootController:self];
menuDelegate.properties = self.currentClient.properties.allObjects;
self.menuViewController.tableView.delegate = self.menuViewController.tableView.dataSource = menuDelegate;
self.menuViewController.delegate = menuDelegate;
[menuDelegate release];
看起来不对。您为menuDelegate指定的属性都不是保留属性。我认为一旦你释放它就会消失,留下悬空指针(除非menuViewController是你自己的类,你已经保留了委托属性)。