簡體   English   中英

從另一個模態視圖控制器調用時ABPeoplePicker崩潰,並且兩者均被消除

[英]Crash in ABPeoplePicker when called from another modal viewcontroller and both dismissed

(注意:我之前在項目上下文中提出了這個問題,但是現在我已經在測試項目中重新創建了崩潰。如果能幫助我告訴我我做錯了什么,將不勝感激。)

從另一個模式視圖控制器調用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,如下所示。 (請注意,您需要將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

原來這是一個實際的錯誤。 的確如此,如果用戶在搜索中單擊某個人時對ABPeoplePicker進行了兩次ModalVC關閉,則會發生此崩潰。 幸運的是,有一個簡單的解決方法:在委托的shouldContinueAfterSelectingPerson中返回YES。 當您同時關閉選擇器時,返回YES或NO並不重要,它不會繼續,但是NO會崩潰而YES不會。 (與我的原始帖子的答案相同: ABPeoplePicker中的怪異崩潰

該錯誤實際上在您的代碼中。 花了我幾分鍾找到它,我將盡力解釋。

  1. 您的ABPeoplePickerNavigationController當前以模態顯示。
  2. 您單擊搜索欄中,然后鍵入一些內容。
  3. 您單擊一個人的名字。

此處發生的是ABPeoplePickerNavigationController詢問其委托人(您的addNewViewController )在選擇一個人后是否應繼續執行。 在等待您的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的各層時,必須非常小心,以與顯示它們相反的順序將其關閉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM