38

我正在开发一个相机应用程序,其中相机视图以模态方式显示。在我完成裁剪之后。我对MainPageViewController. (请看截图)

故事板

我里面MainPageViewController的展开功能如下;

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

MainPageViewController其中 "categories" 是从to的 push segue 标识符CategoriesTableViewController

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

注意:我发现了同样的问题,但答案建议更改情节提要结构。

4

7 回答 7

59

聚会有点晚了,但我找到了一种不使用州旗的方法

注意:这仅适用于 iOS 9+,因为只有自定义转场支持 iOS9 之前的类名,并且您不能将退出转场声明为故事板中的自定义转场

1. 使用 UIStoryboardSegueWithCompletion 子类化 UIStoryboardSegue

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

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

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

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

从情节提要中选择退出 segue 添加自定义类

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

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

您的代码现在将在 exit segue 完成其转换后执行

于 2016-06-02T21:27:05.263 回答
12

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

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

var fromCamera = false

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

我在执行 unwind segue from 之前设置fromCamera为. 通过这种方式,我仅在执行从裁剪视图中展开转场时才执行转场到类别屏幕。trueCropViewController

于 2014-12-16T12:31:26.303 回答
6

提出这个答案(我只有 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
于 2016-07-05T07:37:43.413 回答
5

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

  1. 使用 UIStoryboardSegueWithCompletion 子类化 UIStoryboardSegue

    类 UIStoryboardSegueWithCompletion: UIStoryboardSegue { var 完成: (() -> Void)?

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

    }

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 的类

注意:此 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];
        };
    }
}

您的代码现在将在 exit segue 完成其转换后执行

于 2017-03-24T17:06:48.347 回答
4

我猜 performSegue 没有触发,因为 unwind segue 还没有完成。目前我唯一能想到的就是延迟调用 performSegue 使用dispatch_after. 不过,这对我来说似乎很“hacky”。

@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
    dispatch_after(1, dispatch_get_main_queue()) { () -> Void in
        self.performSegueWithIdentifier("Categories", sender: self)
    }
}
于 2014-12-15T19:56:15.040 回答
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()
        }
    }
}
于 2020-04-07T03:21:31.320 回答
3

exit segue IBAction 方法发生在实际的 unwind 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)
}

希望这对遇到此问题并且只想立即过渡的其他人有所帮助!

于 2015-09-24T22:40:20.743 回答