2011-01-31 1 views
1

(Примечание: Я задал этот вопрос раньше в контексте моего проекта, но теперь я воссоздал авария в тестовом проекте. Любая помощь в том, чтобы сообщить мне, что я «Неправильное поведение было бы оценено.)Сбой в ABPeoplePicker при вызове из другого модального диспетчера просмотров и оба отклоненных

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

Аварийная ситуация возникает, если вы используете окно поиска в сборщике людей, а затем выберите одного из получателей. (Если вы используете симулятор, вам нужно добавить человека в Контакты, прежде чем запускать программу.) Программа вернется, но во время увольнения двух модальных VC я получаю ошибку с ошибкой утверждения. Это происходит каждый раз на iphone, ipad и симуляторах для обоих. Это кажется очень нормальным делом, поэтому мне трудно поверить, что это настоящая ошибка. Сообщение крах:

недостаточность Утверждение в - [ABMembersSearchDisplayController SetActive: анимированные:], /SourceCache/UIKit_Sim/UIKit-1448.69/UISearchDisplayController.m:589 2011-01-31 13: 51: 11,903 testcrasher2 [26044: 207] * Нагрузочного приложение из-за неперехваченный исключения 'NSInternalInconsistencyException', причины: 'поиск содержания навигации контроллер не должен меняться между -SETACTIVE: ДА и -SETACTIVE: нЕТ'

Чтобы продемонстрировать, в новом приложении iPhone Window Xcode я модифицирую команду 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

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

+0

Apple сообщает, что теперь это исправлено в 5.0 – mackworth

1

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

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

+0

Так что я положил это, и авария действительно исчезла. Во время увольнения parentModalVC родителя (в контроллереDidFinish), однако, он жаловался на две «попытки отклонить контроллер модального представления, представление которого в настоящее время не отображается». Итак, я выбрал этот вариант, и он отлично работает. Большое спасибо. – mackworth

+0

ОДНАКО, я не совсем понимаю, поскольку в документации Apple говорится: «Например, если пользователь отменяет текущую операцию, вы можете удалить все объекты в цепочке, отклонив первый модально представленный контроллер представлений. Другими словами, отклонение модального диспетчер просмотра отклоняет не только этот контроллер просмотра, но и любые контроллеры представлений, которые он представил в моделях ». Так не должно ли увольнение родителей быть подходящим для обоих из них? – mackworth

+0

Итак ... немного поговорил. Удаление функции parentModalVC родителя означает, что я не выхожу на него, просто для ребенка. Но затем отменил (что делает родительский увольнение), затем работал. Вернувшись обратно, я получаю эти «попытки уволить». Итак ... как обходной путь, я добавил: «[self performSelector: @selector (rejectModalVC) withObject: nil afterDelay: 0.5];" чтобы позволить ребенку уволить до того, как родитель также уволен. Уродливо, но, похоже, это работает. – mackworth