Сбой в ABPeoplePicker при вызове из другого модального viewcontroller и оба отклонены - PullRequest
1 голос
/ 01 февраля 2011

(Примечание. Ранее я задавал этот вопрос в контексте своего проекта, но теперь воссоздаю сбой в тестовом проекте. Любая помощь в объяснении того, что я делаю неправильно, будет принята с благодарностью.)

Сбой происходит при вызове ABPeoplePicker из другого модального viewcontroller. В частности, в главном окне есть NavController, который загружает myVC. Затем myVC загружает модальный NavController, содержащий мой контроллер, который затем вызывает ABPeoplePicker. В этой демонстрационной программе вмешательство пользователя не требуется, пока не запустится ABPeoplePicker.

Сбой происходит, если вы используете окно поиска в средстве выбора людей, а затем выбираете одного из получающихся людей. (Если вы используете симулятор, вам нужно добавить человека в «Контакты», прежде чем запускать программу.) Программа возвращается, но во время закрытия двух модальных ВК я получаю ошибку ошибки утверждения. Это происходит каждый раз на 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: ДА и -setActive: НЕТ '

Итак, чтобы продемонстрировать, что в новом приложении Xcode для iPhone я изменяю 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

Ответы [ 2 ]

2 голосов
/ 18 февраля 2011

Оказывается, это фактическая ошибка.Это действительно так, что если вы дважды удаляете ModalVC из ABPeoplePicker, когда пользователь нажимает на человека в поиске, вы получите этот сбой.К счастью, существует простой обходной путь: верните YES в mustContinueAfterSelectingPerson вашего делегата.Поскольку вы одновременно отклоняете средство выбора, на самом деле не имеет значения, возвращаете ли вы ДА или НЕТ, оно не будет продолжаться, но НЕТ будет аварийно завершать работу, а ДА - нет.(Тот же ответ, что и для моего оригинального сообщения: Странный сбой в ABPeoplePicker )

1 голос
/ 01 февраля 2011

Ошибка на самом деле в вашем коде. Мне понадобилось несколько минут, чтобы найти его, я постараюсь объяснить как можно лучше.

  1. Your ABPeoplePickerNavigationController в настоящее время представлен модально.
  2. Вы нажимаете в строке поиска и вводите некоторые вещи.
  3. Вы нажимаете на имя человека.

Что происходит здесь, 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, вы должны быть очень осторожны, чтобы отклонить их в обратном порядке, в котором вы их представили.

...