xcode performSegueWithIdentifier 和 prepareForSegue

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17202534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 03:31:44  来源:igfitidea点击:

performSegueWithIdentifier and prepareForSegue

xcodestoryboard

提问by MichelleJS

I have a UIViewController *vc1with 4 buttons. Each button causes a push segue to another UIViewController *vc2. vc2is shows some information based on which button was pushed. I pass the infomation from vc1to vc2in vc1's prepareForSegue(its just an int value). This all works fine. Now I need to make it so that the vc2will also be called if the iphone is both on vc1(vc1isVisible) and a vc1receives a UINotification(something happens with a bluetooth device). Here is my code:

我有一个UIViewController *vc1带 4 个按钮的。每个按钮都会导致一个 push segue 到另一个UIViewController *vc2vc2是根据按下的按钮显示一些信息。我通过信息来源从vc1vc2vc1prepareForSegue(它只是一个int值)。这一切正常。现在我需要这样做,以便vc2在 iphone 处于开启状态vc1vc1isVisible)和vc1接收 a UINotification(蓝牙设备发生某些事情)时也会调用。这是我的代码:

-(void) eventDetected:(NSNotification *)notification{
    if(self.isViewLoaded && self.view.window){
        [self performSegueWithIdentifier:@"detected" sender:self];
    }
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    VC2 *destination = [segue destinationViewController];
    [destination setValue:value];
}

Right now if the proper event happens vc2loads twice, instead of once. And I get these error messages in the output logs:

现在,如果正确的事件发生vc2加载两次,而不是一次。我在输出日志中收到这些错误消息:

"Nested push animation can result in corrupted navigation bar" & "Unbalanced calls to begin/end appearance transitions for .corrupted. & "Finishing up a navigaion transition in an unexpected state. Navigation Bar subview tree might get corrupted.

“嵌套推送动画可能会导致导航栏损坏”和“对 .corrupted 的开始/结束外观转换的调用不平衡。”和“在意外状态下完成导航转换。导航栏子视图树可能会损坏。

These errors happen after I press the back button. I added NSLogstatements which is why I know that vc2's viewDidLoadis getting called twice every time.

我按下后退按钮后会发生这些错误。我添加了NSLog语句,这就是为什么我知道vc2'sviewDidLoad每次都会被调用两次。

I created the push segues for all 4 buttons using the storyboard. I have not labelled them. I created the event push segue through the storyboard as well and gave it the identifier "detected". I hope someone on here has some idea about what I am doing wrong. Would appreciate advice. Thanks.

我使用故事板为所有 4 个按钮创建了 push segues。我没有给它们贴上标签。我也通过情节提要创建了事件推送segue,并给了它 identifier "detected"。我希望这里有人对我做错了什么有一些想法。将不胜感激的建议。谢谢。

Here is the current code:

这是当前的代码:

-(void)viewDidAppear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exerciseDetected:) name:@"ExerciseDetected" object:nil];
    [[NSNotifcationCenter defaultCenter] addObserver:self selector:@selector(cancelExercise:) name@"cancelExercise" object:nil];
}
-(void)exerciseDetected:(NSNotification *)notification{
    if(self.isViewLoaded && self.view.window){
        if(self == self.navigationController.topViewController){
            if(!timerRunning){
                timerRunning =YES;
                _exerciseTimer = (NSTimer scheduledTimerWithTimeInterval:EXERCISE_AUTOSTART_TIME target:self selector:@selector(startExercise:) userInfo:nil repeats:NO];
            }
        }
    }
}
-(void)cancelExercise:(id)sender{
    [_exerciseTimer invalidate];
    timerRunning = NO;
}
-(void) startExercise: (id)sender{
    timerRunning = NO;
    [self performSegueWithIdentifier:@"detected" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
     vc2 *destination = [segue destinationViewController];
    [destination setSElectedExerciseIDFromMenu:_selectedExercise];
}

回答by GayleDDS

You should definitely only call performSegueWithIdentifier when self is the top view controller

当 self 是顶视图控制器时,你绝对应该只调用 performSegueWithIdentifier

if (self == self.navigationController.topViewController) {

    ...
}

If you need to be sure something is only called once you can do:

如果您需要确保某事只被调用一次,您可以执行以下操作:

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    [self foo];
});

If you need to run something in the next run loop execution you can do:

如果您需要在下一个运行循环执行中运行某些内容,您可以执行以下操作:

dispatch_async(dispatch_get_main_queue(), ^{
    [self bar];
});