(注意:我之前在项目的上下文中提交了这个问题,但我现在已经在测试项目中重新创建了崩溃。任何帮助告诉我我做错了什么都会受到赞赏。)
从另一个模态viewcontroller调用ABPeoplePicker时发生崩溃。具体来说,主窗口有一个NavController,它加载myVC。 myVC然后加载一个包含我的控制器的模态NavController,然后调用ABPeoplePicker。在此演示程序中,在ABPeoplePicker运行之前,无需用户干预。
如果您使用人员选择器中的搜索框,然后选择其中一个结果人员,则会发生崩溃。 (如果你使用模拟器,你需要在运行程序之前在Contacts中添加一个人。)程序返回,但在解雇两个模态VC期间,我得到一个断言错误崩溃。它每次都出现在iphone,ipad和模拟器上。这似乎是很正常的事情,所以我发现很难相信这是一个真正的错误。崩溃消息是:
断言失败 - [ABMembersSearchDisplayController setActive:animated:], /SourceCache/UIKit_Sim/UIKit-1448.69/UISearchDisplayController.m:589 2011-01-31 13:51:11.903 testcrasher2 [26044:207] * 由于未被捕获而终止应用程序 例外 'NSInternalInconsistencyException', 原因:'搜索内容导航 控制器之间不能改变 -setActive:YES和-setActive:NO'
所以为了演示,在一个新的Xcode iPhone Window应用程序中,我修改了didFinishLaunchingWithOptions来调用我的控制器。然后我按如下方式创建两个VC。 (注意,您需要将Addressbook框架添加到目标。)这是整个程序......
AppDelegate.didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myViewController *detailViewController = [[myViewController alloc] init];
// Set the navigation controller as the window's root view controller and display.
UINavigationController * navController = [[UINavigationController alloc] initWithRootViewController: detailViewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
[detailViewController release];
[navController release];
return YES;
}
myViewController.h:
@interface myViewController : UIViewController<addDelegate>{
}
@end
myViewController.m:
#import "myViewController.h"
#import "AddNewViewController.h"
@implementation myViewController
- (void)controllerDidFinish:(addNewViewController *)controller {
[self dismissModalViewControllerAnimated:YES];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear: animated];
addNewViewController *addController = [[addNewViewController alloc] init];
addController.delegate = self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addController];
[self presentModalViewController:navController animated:YES];
[navController release];
[addController release];
}
@end
AddNewViewController.h:
#import <AddressBookUI/AddressBookUI.h>
@protocol addDelegate;
@interface addNewViewController : UIViewController < ABPeoplePickerNavigationControllerDelegate> {
id <addDelegate> delegate;
}
@property(nonatomic, assign) id <addDelegate> delegate;
@end
@protocol addDelegate <NSObject>
- (void)controllerDidFinish:(addNewViewController *)controller ;
@end
AddNewViewController.m:
#import "AddNewViewController.h"
@implementation addNewViewController
@synthesize delegate;
-(void) viewDidAppear:(BOOL)animated {
ABPeoplePickerNavigationController * peoplepicker = [[ABPeoplePickerNavigationController alloc] init] ;
peoplepicker.peoplePickerDelegate = self;
[self presentModalViewController:peoplepicker animated:YES];
[peoplepicker release];
}
#pragma mark AddressBook delegate methods
- (void)peoplePickerNavigationControllerDidCancel: (ABPeoplePickerNavigationController *)peoplePicker {
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
[self.delegate controllerDidFinish:self ];
return NO; //EDIT: This MUST be YES or it will crash (see answer below)
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier {
return NO;
}
@end
答案 0 :(得分:2)
原来这是一个真正的错误。确实如果你在用户点击搜索中的某个人时对你的ABPeoplePicker进行双重ModalVC解雇,你就会遇到这种崩溃。幸运的是,有一个简单的解决方法:在委托中输入YESContinueAfterSelectingPerson。当你同时解雇选择器时,无论你返回YES还是NO都没关系,它不会继续,但是NO会崩溃,YES则不会。 (与我原来的帖子答案相同:Weird crash in ABPeoplePicker)
答案 1 :(得分:1)
该错误实际上在您的代码中。花了几分钟才找到它,我会尽力解释。
ABPeoplePickerNavigationController
目前以模态呈现。这里发生了什么,是ABPeoplePickerNavigationController
询问其代表(您的addNewViewController
)是否应该在选择一个人后继续。在等待您回复的同时,您突然调用自己的协议方法(在myViewController
中)尝试关闭模式addNewViewController
。由于ABPeoplePickerNavigationController
仍处于打开状态,你已经超越了自己。
将ABPeoplePickerNavigationControllerDelegate方法的实现更改为:
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
// This line is new.
[self.navigationController dismissModalViewControllerAnimated:YES];
[self.delegate controllerDidFinish:self];
return NO;
}
你的崩溃将会消失。当你在UIViewControllers和UINavigationControllers层上处理图层时,你必须非常小心地按照你提出的相反顺序来解雇它们。