2013-03-26 1 views
0

У меня есть иерархия UIViewControllers, которые были представлены с использованием методов currentModalViewController.UIViewController отклоняет несколько контроллеров (iOS 4.3 и выше)

У меня есть singleton, которые захватывают все представленные контроллеры представлений массиву.

Например я представил контроллер А затем В и затем С. Каждый контроллер я вставил в индекс 0.

Таким образом, у меня есть иерархия, как показано ниже

C

В

A

это мой синглтон

@implementation PresentHelper

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.viewControllers = [NSMutableArray new]; 
    } 
    return self; 
} 

+ (PresentHelper *)sharedInstance 
{ 
    static dispatch_once_t pred; 
    static PresentHelper *sharedInstance = nil; 
    dispatch_once(&pred, ^{ 
     sharedInstance = [[self alloc] init]; 
    }); 
    return sharedInstance; 
} 

- (void)backToViewControllerA 
{ 
    for (UIViewController *controller in self.viewControllers) { 
     [controller dismissModalViewControllerAnimated:NO]; 
    } 
    [self.viewControllers removeAllObjects]; 
} 

@end 

В UIViewController C Слово backToViewControllerA метод.

Поэтому, когда я отлаживал этот метод, мне было интересно, почему метод - viewDidLoad (для каждого контроллера в self.viewControllers) вызывается после этой строки [controller dismissModalViewControllerAnimated:NO];, поскольку я думаю, что это не должно работать так, но оно работает.

Итак, возможно, это не один из способов возврата к контроллеру вида A, но в любом случае мой вопрос связан с методом viewDidLoad.

Также это мой код ниже, как я представляю каждый контроллер. У меня есть базовый класс, и каждый (A, B, C-контроллеры унаследованы от него).

- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated 
{ 
    PresentHelper *presentHelper = [PresentHelper sharedInstance]; 
    [presentHelper.viewControllers insertObject:modalViewController atIndex:0]; 
    [super presentModalViewController:modalViewController animated:animated]; 
} 

Также получил сообщение

NSArray мутировали, будучи перечислены

Так как я думаю, что после того, как уволить теряю объект и, может быть, это моя проблема.

+0

Итак ... вы задаетесь вопросом о поведении viewDidLoad, или вы спрашиваете, что является лучшим способом получить от C до A? Является ли причина _entire_ для Singleton просто для облегчения навигации назад к A с C? Должно ли решение быть совместимым с iOS4.3? – foundry

+0

вопрос касательно лучший способ. Я нашел странное поведение, и это связано с мутировавшим моим массивом и, как я думаю, не связано с viewDidLoad. спасибо –

+0

Нужно ли работать на iOS4.3? Это важное различие в отношении возможных решений. – foundry

ответ

1

Это не кажется хорошим использование Singleton.

Существует несколько способов, по которым вы можете вернуться к A. Вам не нужно создавать дополнительные методы или свойства делегата, так как каждый контроллер имеет ссылку на предыдущий через его свойство presentingViewController. (Я перефразирую это ...для iOS5 + вы можете использовать встроенное свойство viewController presentingViewController). Для того, чтобы остаться совместимым с iOS4.3, делают недвижимость и положить его в базовом классе @interface:

@property (nonatomic, assign) UIViewController* presentingController; 

Также в интерфейсе базы Clase, объявить метод:

- (void) dismissBackToA; 

В @implementation, @synthesize ваше имущество и определить dismissBackToA

- (void) dismissBackToA 
{ 
    if ([[self presentingController] respondsToSelector:@selector(dismissBackToA)]) { 
      [[self presentingController] performSelector:@selector(dismissBackToA)]; 
    } 
} 

в вашем модальном настоящем кодексе, установить ссылку на себя в пре sented VC - например:

MasterViewController* BViewController = [[BViewController alloc] init]; 
    BViewController.presentingController = self; 
    [self presentModalViewController:BViewController animated:YES]; 

Теперь все, что вам нужно сделать, это переопределить dismissBackToA в вашем AViewController подкласса:

- (void) dismissBackToA 
{ 
    [self dismissModalViewControllerAnimated:YES]; 

} 

Это позволит вам шлейфового любое количество модальных viewControllers ... родового dismissBackToA будет «разматывать» цепочку обратно до метода A. A override, который отклонит его модальный (B). Этот должен уничтожить все остальные контроллеры в цепи. presentController действует в значительной степени как стандартный делегат - я сделал это, чтобы подчеркнуть его сходство с presentingViewController в iOS5 +. Я немного ржавый в памяти nonArc, но я думаю, что его нужно назначить не сохраненным.

Я боюсь, что я не могу проверить это 100%, так как я не имею iOS4.3 тренажер под рукой ...

обновление

Вы также можете просто передать ссылку до А до конца цепи и отправить [self.referenceToA dismissModalViewControllerAnimated:YES] всякий раз, когда вам нужно, но этот способ чувствует себя немного более общим.

Вы также должны остерегаться, что presentModalViewController:animated: и dismissModalViewControllerAnimated: являются DEPRECATED в 6.0: теперь вы должны использовать

- presentViewController:animated:completion: 
- dismissViewControllerAnimated:completion: 

, которые были введены в 5.0.

Они по-прежнему работают, но принимайте это за предупреждение - вы должны быть готовы отказаться от поддержки 4.3 или сделать свой код условным для версии ОС в будущем.

+0

Я не уверен, что у меня есть точка. У меня есть BaseViewController для контроллеров A, B и C (A: BaseViewController, B: BaseViewController и C: BaseViewController). Когда я нажимаю на кнопку «Главная», мне нужно отменить контроллер C и B. Я внедрил ваш код в контроллере базового представления, но, возможно, мы говорим о разных вещах. –

+0

У меня есть =) Мне просто нужно позвонить [super rejectBackToA] вместо [self rejectBackToA] –

+0

@MatrosovAlexander - проверить мой обновленный ответ, вам нужно позаботиться о будущем, поскольку вы используете устаревшие методы ... – foundry

0

Это нехороший способ отклонить ваши контроллеры. Создание синглтона только для этой цели кажется плохим. Самым простым способом было бы сделать это в раскадровке, используя развязку segue, но это будет работать только для iOS 6, я думаю (возможно, iOS 5 тоже). Если вы хотите сделать это в коде, то вы должны использовать делегирование или NSNotifications, чтобы иметь A увольнение C (которое также отклоняет B). Кроме того, если вы собираетесь представлять модульные контроллеры представлений в коде, вы не должны использовать этот обесцененный метод, используйте presentViewController: анимированный: завершение: вместо этого.

После редактирования:

Вы также можете сделать это, как это от контроллера C:

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 
+0

OP указывает iOS4.3 и выше ... так что Раскадровки или без разматывания разрешены. – foundry

+0

спасибо за ответ, но мне это нужно для iOS 4.3 –

+0

@MatrosovAlexander, да, я только что заметил и отредактировал свой ответ. – rdelmar