关闭模态视图后,父视图似乎已解除分配?
我正在编写一个 iPhone 应用程序。从导航堆栈中的视图控制器 [称为 EditCreatorController] 开始,我将呈现一个自定义模式视图控制器 [称为 BMSStringPickerController]。我已经根据 Apple 指南创建了委托协议等,用于将数据传递回第一个视图并使用该视图来关闭模式视图。我什至从模态控制器获取了预期的数据,并且能够很好地忽略它。问题是,此时,我对原始视图控制器执行的几乎任何操作都会导致调试器错误,例如
-[EditCreatorController PerformSelector:withObject:withObject:]: message sent to deallocated instance 0x3a647f0
或
-[EditCreatorController tableView:willSelectRowAtIndexPath:]:消息发送到已释放的实例 0x3c12c40
换句话说,当模态视图显示时,原始视图控制器似乎已经消失。无论调用两个委托回调中的哪一个,都是如此。
这是来自父控制器的调用模态视图的代码:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 1) { // selection on creator type row
// create a string picker to choose new creator type from list
BMSStringPickerController *picker = [[BMSStringPickerController alloc] initWithNibName:@"BMSStringPickerController" bundle:nil];
picker.delegate = self;
picker.stringChoices = [NSArray arrayWithObjects:@"composer", @"lyricist", @"arranger", @"original artist", @"other", nil];
picker.currentChoice = creator.type;
picker.title = @"Creator Type";
// wrap it in a nav controller so we can get tile bar etc. (from VC prog guide p. 93)
UINavigationController *newNavigationController = [[UINavigationController alloc]
initWithRootViewController:picker];
[self.navigationController presentModalViewController:newNavigationController animated:YES];
[newNavigationController release];
[picker release];
}
}
这是委托回调:
- (void)stringPickerController:(BMSStringPickerController *)picker didPickString:(NSString *)string {
NSLog(@"received string back: %@", string);
typeLabel.text = string; // only change the label for now; object only changes if done button pressed
[self.tableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
- (void)stringPickerControllerDidCancel:(BMSStringPickerController *)picker {
NSLog(@"picker cancelled");
[self dismissModalViewControllerAnimated:YES];
}
另一个奇怪的事情(也许是线索)是,虽然我收到“收到的字符串返回” NSLog 消息,并将其分配给 typeLabel.text (typeLabel 是我的表视图中标签的 IBOutlet),即使重新加载表,它也永远不会出现在那里。
有人有一些想法吗?
I'm writing an iPhone app. Starting from a view controller in a navigation stack [called EditCreatorController], I am presenting a custom modal view controller [called BMSStringPickerController]. I have created a delegate protocol, etc. per the Apple guidelines for passing data back to the first view and using that view to dismiss the modal view. I even get the expected data back from the modal controller and am able to dismiss it just fine. The problem is, at that point, almost any action I take on the original view controller leads to debugger errors like
-[EditCreatorController performSelector:withObject:withObject:]: message sent to deallocated instance 0x3a647f0
or
-[EditCreatorController tableView:willSelectRowAtIndexPath:]: message sent to deallocated instance 0x3c12c40
In other words, it seems like the original view controller has evaporated while the modal view was showing. This is true no matter which of the two delegate callbacks is invoked.
Here is the code from the parent controller that invokes the modal view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 1) { // selection on creator type row
// create a string picker to choose new creator type from list
BMSStringPickerController *picker = [[BMSStringPickerController alloc] initWithNibName:@"BMSStringPickerController" bundle:nil];
picker.delegate = self;
picker.stringChoices = [NSArray arrayWithObjects:@"composer", @"lyricist", @"arranger", @"original artist", @"other", nil];
picker.currentChoice = creator.type;
picker.title = @"Creator Type";
// wrap it in a nav controller so we can get tile bar etc. (from VC prog guide p. 93)
UINavigationController *newNavigationController = [[UINavigationController alloc]
initWithRootViewController:picker];
[self.navigationController presentModalViewController:newNavigationController animated:YES];
[newNavigationController release];
[picker release];
}
}
And here are the delegate callbacks:
- (void)stringPickerController:(BMSStringPickerController *)picker didPickString:(NSString *)string {
NSLog(@"received string back: %@", string);
typeLabel.text = string; // only change the label for now; object only changes if done button pressed
[self.tableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
- (void)stringPickerControllerDidCancel:(BMSStringPickerController *)picker {
NSLog(@"picker cancelled");
[self dismissModalViewControllerAnimated:YES];
}
Another weird thing (perhaps a clue) is that although I get the "received string back" NSLog message, and assign it to typeLabel.text (typeLabel is an IBOutlet to a label in my table view), it never appears there, even with the table reload.
Anyone have some ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
也许您在
BMSStringPickerController
的dealloc
中释放了delegate
?Maybe you release the
delegate
indealloc
ofBMSStringPickerController
?它可能无法解决您的问题,但我建议告诉选择器自行解散(在委托方法中),从而允许响应者链正确处理解散:
It may not solve your problem, but I suggest telling the picker to dismiss itself (in the delegate methods), allowing the responder chain to correctly handle the dismiss:
出现内存警告时的默认行为是释放所有不可见视图控制器的视图。因此,如果在模态视图控制器中出现内存警告,则其父视图控制器可能会卸载其视图。
发生这种情况时,视图控制器上会调用 viewDidUnload ,以便您可以释放保留在视图中的任何引用。如果您有未保留的引用,则在卸载视图时它们将变得无效。也许您的情况正在发生这种情况?
请参阅 UIViewController 参考内存管理部分了解详细信息。 UIViewController 方法 didReceiveMemoryWarning:如果视图当前不可见,则释放视图,然后调用viewDidUnload。
The default behavior when there is a memory warning is the release the view of all view controllers that are not visible. So if there was a memory warning while in your modal view controller, its parent view controller could have its view unloaded.
When this happens, viewDidUnload is called on the view controller so that you can release any references you hold into the view. If you have references that you didn't retain they will become invalid when the view is unloaded. Maybe this is happening in your case?
See the UIViewController reference Memory Management section for details. The UIViewController method didReceiveMemoryWarning: releases the view if the view is not currently visible and then calls viewDidUnload.