1

(注意:我之前在我的项目的上下文中提出了这个问题,但我现在已经在一个测试项目中重新创建了崩溃。任何帮助告诉我我做错了什么将不胜感激。)

从另一个模态视图控制器调用 ABPeoplePicker 时会发生崩溃。具体来说,主窗口有一个 NavController,它加载 myVC。myVC 然后加载一个包含我的控制器的模态 NavController,然后调用 ABPeoplePicker。在此演示程序中,在 ABPeoplePicker 运行之前无需用户干预。

如果您使用人员选择器中的搜索框,然后选择结果人员之一,则会发生崩溃。(如果您使用模拟器,则需要在运行程序之前在联系人中添加一个人。)程序返回,但在关闭两个模态 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,如下所示。(请注意,您需要将地址簿框架添加到目标。)这是整个程序...

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
4

2 回答 2

2

事实证明这是一个实际的错误。确实,如果您在用户单击搜索中的人时对 ABPeoplePicker 执行双重 ModalVC 关闭,您将遇到此崩溃。幸运的是,有一个简单的解决方法:在您的委托的 shouldContinueAfterSelectingPerson 中返回 YES。当您同时关闭选择器时,返回 YES 或 NO 并不重要,它不会继续,但 NO 会崩溃而 YES 不会。(与我原来的帖子相同的答案:ABPeoplePicker 中的奇怪崩溃

于 2011-02-18T00:56:27.563 回答
1

该错误实际上在您的代码中。我花了几分钟才找到它,我会尽力解释。

  1. ABPeoplePickerNavigationController 目前以模态方式呈现。
  2. 您单击搜索栏并输入一些内容。
  3. 你点击一个人的名字。

这里发生的是ABPeoplePickerNavigationController询问它的代表(即你的addNewViewController)在选择一个人后是否应该继续。在它等待您的回复时,您突然调用了您自己的协议的方法 (in myViewController),该方法试图解除 modal 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 时,你必须非常小心地以与你呈现它们相反的顺序来解除它们。

于 2011-02-01T00:56:37.183 回答