在展开segue之后执行push segue

时间:2014-12-15 12:15:22

标签: ios xcode swift unwind-segue

我正在使用相机应用程序,其中相机视图以模态显示。完成裁剪后。我执行MainPageViewController的展开segue。 (请参见截图)

storyboard

MainPageViewController内的我的展开功能如下:

@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
    self.performSegueWithIdentifier("Categories", sender: self)
}

其中"类别"是从MainPageViewControllerCategoriesTableViewController的推送segue标识符。

程序进入unwindToMainMenu功能,但不执行push segue。知道如何解决这个问题吗?

注意:我找到了相同的question,但答案建议更改故事板结构。

7 个答案:

答案 0 :(得分:45)

派对有点晚了,但我发现了一种不使用状态标志的方法

注意:这仅适用于iOS 9+,因为只有自定义segues支持iOS9之前的类名,并且您无法在故事板中将exit segue声明为自定义segue

1。子类UIStoryboardSegue与UIStoryboardSegueWithCompletion

class UIStoryboardSegueWithCompletion: UIStoryboardSegue {
    var completion: (() -> Void)?

    override func perform() {
        super.perform()
        if let completion = completion {
            completion()
        }
    }
}

2。将UIStoryBoardSegueWithCompletion设置为退出segue的类

注意:此segue的操作应为unwindToMainMenu以匹配原始问题

Select exit segue from storyboard Add custom class

3。更新unwind @IBAction以执行完成处理程序中的代码

@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
    if let segue = segue as? UIStoryboardSegueWithCompletion {
        segue.completion = { 
            self.performSegueWithIdentifier("Categories", sender: self) 
        }
    }
}

您的代码现在将在退出segue完成转换后执行

答案 1 :(得分:11)

我想暂时为这个问题提供自己的解决方案。任何进一步的答案总是受欢迎的。

我将一个布尔变量和viewDidAppear函数放到MainPageViewController

var fromCamera = false

override func viewDidAppear(animated: Bool) {
    if fromCamera {
        self.performSegueWithIdentifier("categorySelection", sender: self)
        self.fromCamera = false
    }
}

在我从fromCamera执行展开segue之前,我将true设置为CropViewController。通过这种方式,只有在执行裁剪视图的展开segue时才执行segue到类别屏幕。

答案 2 :(得分:6)

前进this answer(我只有Objective-C代码)

子类UIStoryBoardSegue

#import <UIKit/UIKit.h>

@interface MyStoryboardSegue : UIStoryboardSegue

/**
 This block is called after completion of animations scheduled by @p self.
 */
@property (nonatomic, copy) void(^completion)();

@end

完成动画后调用此完成块。

@implementation MyStoryboardSegue

- (void)perform {
  [super perform];
  if (self.completion != nil) {
    [self.destinationViewController.transitionCoordinator
     animateAlongsideTransition:nil
     completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
       if (![context isCancelled]) {
         self.completion();
       }
     }];
  }
}

@end

答案 3 :(得分:5)

前面两个答案,这里有关于目标c版本的更多细节(我也只有Objective-C代码)

  1. 子类UIStoryboardSegue与UIStoryboardSegueWithCompletion

    class UIStoryboardSegueWithCompletion:UIStoryboardSegue {     var completion:(() - &gt; Void)?

    override func perform() {
        super.perform()
        if let completion = completion {
            completion()
        }
    }
    

    }

  2. UIStoryboardSegueWithCompletion.h

    #import <UIKit/UIKit.h>
    
    @interface MyStoryboardSegue : UIStoryboardSegueWithCompletion
    
    @property (nonatomic, copy) void(^completion)();
    
    @end
    

    UIStoryboardSegueWithCompletion.m

    #import "UIStoryboardSegueWithCompletion.h"
    
    @implementation UIStoryboardSegueWithCompletion
    
    - (void)perform {
      [super perform];
      if (self.completion != nil) {
        [self.destinationViewController.transitionCoordinator
         animateAlongsideTransition:nil
         completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
           if (![context isCancelled]) {
             self.completion();
           }
         }];
      }
    }
    @end
    
    1. 将UIStoryBoardSegueWithCompletion设置为退出segue的类
    2. 注意:此segue的操作应该是unwindToMainMenu以匹配原始问题 [图像显示segue ui] [1] [图像显示segue ui 2] [2]

      从故事板中选择退出segue添加自定义类

      -(IBAction)unwindToMainMenu(UIStoryboardSegue *)segue {
          if([segue isKindOfClass:[UIStoryboardSegueWithCompletion class]]){
              UIStoryboardSegueWithCompletion *segtemp = segue;// local prevents warning
              segtemp.completion = ^{
                  NSLog(@"segue completion");
                  [self performSegueWithIdentifier:@"Categories" sender:self];
              };
          }
      }
      

      您的代码现在将在退出segue完成转换后执行

答案 4 :(得分:4)

我猜测performSegue没有触发因为unwind segue还没有完成。我目前唯一能想到的就是延迟使用dispatch_after调用performSegue。这看起来非常&#34; hacky&#34;对我而言。

@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
    dispatch_after(1, dispatch_get_main_queue()) { () -> Void in
        self.performSegueWithIdentifier("Categories", sender: self)
    }
}

答案 5 :(得分:3)

退出segue IBAction方法在实际展开segue完成之前发生。我有同样的问题并以这种方式解决(如果你不介意我的代码解释)。它避免了依赖ViewDidAppear的额外时间和动画。

@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
   let categoriesTable = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("CategoryTableViewController")
   self.navigationController?.viewControllers.append(categoriesTable)
   self.navigationController?.showViewController(categoriesTable, sender: self)
}

希望这对遇到这种情况并且只是想要瞬间过渡的其他人有帮助!

答案 6 :(得分:3)

更新了@moride对 Swift 5 的回答。过渡协调器现在是可选的,因此在这种情况下,我们将立即运行完成。

class UIStoryboardSegueWithCompletion: UIStoryboardSegue {
    var completion: (() -> Void)?

    override func perform() {
        super.perform()

        guard let completion = completion else { return }
        guard let coordinator = destination.transitionCoordinator else {
            completion()
            return
        }

        coordinator.animate(alongsideTransition: nil) { context in
            guard !context.isCancelled else { return }
            completion()
        }
    }
}