Могу ли я использовать segues с назначенными инициализаторами контроллеров представления? - PullRequest
10 голосов
/ 21 января 2012

Я новичок в раскадровках и настроил переход от кнопки к контроллеру представления. Этот контроллер представления имеет пользовательский подкласс SFListViewController, который имеет назначенный инициализатор initWithList:.

Использование назначенного инициализатора - единственный способ правильно инициализировать контроллер представления. Однако при использовании сегментов назначенный инициализатор вызываться не будет (очевидно).

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  if ([segue.identifier isEqualToString:@"Show List"]) {
    SFListViewController *listViewController = segue.destinationViewController;
    // ????
  }
}

Как я могу заставить segue вызывать назначенный инициализатор при выполнении?

1 Ответ

5 голосов
/ 21 января 2012

Насколько я знаю, это невозможно, поскольку среда раскадровки просто вызывает alloc и init для класса, который вы определяете в Interfacebuilder. Кроме того, атрибут segue destinationViewController доступен только для чтения, поэтому вы не можете просто заменить существующий ViewController.

Единственным способом использования раскадровки, вероятно, было бы создание класса-оболочки, который внутренне создает экземпляр SFListViewController с требуемыми атрибутами, а затем функционирует как прокси-объект и, таким образом, распространяет viewDid*** и viewWill*** -методы на обернутый класс и также возвращает представление обернутого VC в только для чтения view свойстве ... Вы понимаете.

Обычно существует несколько альтернативных способов инициализации UIViewController в таком случае:

  1. Существует возможность указать «Определенные пользователем атрибуты времени выполнения», которые можно использовать для инициализации.

  2. Переопределите метод prepareForSegue:, как вы пытались, в своем корневом ViewController и выполните там "post-alloc-init-initialisation".

  3. Если худшее наихудшее, вы можете вернуться к IBAction, чтобы иметь возможность инициализировать ViewController самостоятельно.

Надеюсь, это поможет.

Редактировать: Я могу убедиться, что Proxy-подход работает, так как я только что столкнулся с подобной проблемой с ABPeoplePickerNavigationController, где этот подход работал хорошо. Поскольку мы настроили эту штуку на нашей доске рассказов, учтите, что вам нужно использовать awakeFromNib для первоначальной настройки (вместо некоторого init метода).

Это код для моего класса оболочки:

#import "PeoplePickerViewControllerWrapper.h"

@implementation PeoplePickerViewControllerWrapper

@synthesize ppvc = _ppvc;  // This is the object I'm proxying (The proxyee so to speak)
@synthesize delegate = _delegate;

- (void)awakeFromNib
{
        self.ppvc = [[ABPeoplePickerNavigationController alloc] init ];
        self.ppvc.peoplePickerDelegate = self;
        self.ppvc.addressBook = ABAddressBookCreate(); 
        self.ppvc.displayedProperties = [NSArray arrayWithObject:[NSNumber numberWithInt:kABPersonPhoneProperty]];
}

#pragma mark - View lifecycle

- (void)loadView
{
    [super loadView];
    [self.ppvc loadView];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.ppvc viewDidLoad];
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.ppvc viewWillAppear:animated];
}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    [self.ppvc viewDidDisappear:animated];
}

-(UIView *)view{
    return self.ppvc.view;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    [self.ppvc viewDidUnload];
}
...