Can I use segues with designated initializers of v

2019-06-16 05:04发布

问题:

I am new to storyboards and I have set up a segue from a button to a view controller. This view controller is of a custom subclass SFListViewController, which has a designated initializer initWithList:.

Using the designated initializer is the only way to correctly initialize the view controller. However, when using segues the designated initializer won't be called (obviously).

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

How can I make the segue call the designated initializer when performed?

回答1:

As far as I know this is not possible since the storyboard framework simply calls alloc and init on the class you define in Interfacebuilder. Additionally the segue's destinationViewController attribute is read-only so you couldn't simply replace the existing ViewController either.

The only way to use Storyboarding would probably be to create a wrapper-class that internally instantiates the SFListViewController with the desired attributes and then functions as a proxy object and thus propagates viewDid*** and viewWill***-methods to the wrapped class and also returning the wrapped VC's view in a readonly view property... You get the idea.

Generally there are a number of alternative ways to initialize a UIViewController in such a case:

  1. There is an option to specify "User defined runtime Attributes" which could be used for initialisation.

  2. Override the prepareForSegue: method, like you tried, in your root ViewController and do "post-alloc-init-initialisation" there.

  3. If worst comes worst, you could fall back to an IBAction in order to be able to initialize the ViewController yourself.

I hope this helps.

Edit: I can verify that the Proxy-Approach works since I just came across a similar problem with ABPeoplePickerNavigationController where this approach worked nicely. Since we've set up the thing in our story board please note that you have to use awakeFromNib in order to do initial configuration (instead of some init method).

This is the code for my wrapper class:

#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];
}