Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a universal app, where I am sharing the same controller for a IPad and IPhone storyboard. I have put a UILongPressGestureRecognizer on a UITableView, that when a cell is pressed on iPhone it calls an action that perform a segue:

-(IBAction)showDetail:(id)sender {
    UILongPressGestureRecognizer *gesture = (UILongPressGestureRecognizer*)sender;
    if (gesture.state == UIGestureRecognizerStateBegan) {
        CGPoint p = [gesture locationInView:self.theTableView];

        NSIndexPath *indexPath = [self.theTableView indexPathForRowAtPoint:p];
        if (indexPath != nil) {
            [self performSegueWithIdentifier:SEGUE_DETAIL sender:indexPath];
        }
    }
}

the segue is a detail view performed as a 'push'. The first thing you should notice is that the sender is an NSIndexPath, is the only way I found for passing the selected cell. Maybe there's a better solution. Everything works fine, in a sense that the segue is performed, and before the prepareForSegue is called too.

However it happens that on iPad, I have changed the segue identifier to Popover. Now things are working in part, the segue is performed, but prepareForSegue is not called and therefore the destination view controller is not set up as it should be.

What am I doing wrong ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
337 views
Welcome To Ask or Share your Answers For Others

1 Answer

What I have discovered so far, is that with any segue identifier that is not popover these are the invocations made by iOS:

  • prepareForSegue (on source controller)
  • viewDidLoad (on destination controller)

while in popover segue the invocation order is:

  • viewDidLoad (on destination controller)
  • prepareForSegue (on source controller)

just because I put all my logic in viewDidLoad, the controller was not properly initialized, and a crash happened. So this is not exactly true that prepareForSegue is not called, the truth is that I was getting an exception, and I wrongly mistaken as prepareForSegue not getting called.

I couldn't put everything in viewWillAppear because a call to CoreData had to be made and I didn't want to check if entities were ok each time the view display.

How did I solve this ? I created another method in destination controller

-(void)prepareViewController {
  // initialization logic...
}

and changing the prepareForSegue method in source controller itself:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  MyViewController *mvc = (MyViewController*)[segue destinationViewController];
  // passing variable 
  // with segue style other than popover this called first than viewDidLoad
  mvc.myProp1=@"prop1"; 
  mvc.myProp2=@"prop2";

  // viewWillAppear is not yet called
  // so by sending message to controller
  // the view is initialized
  [mvc prepareViewController];

}

don't know if this is expected behavior with popover, anyway now things are working.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...