xcode 在展开转场后执行推转转场

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27483881/
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 06:21:58  来源:igfitidea点击:

Perform push segue after an unwind segue

iosxcodeswiftunwind-segue

提问by Berkan Ercan

I am working on a camera app where the camera views are shown modally. After I am done with cropping. I perform an unwind segue to the MainPageViewController. (Please see the screenshot)

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

storyboard

故事板

My unwind function inside MainPageViewControlleris as follows;

我里面的 unwind 功能MainPageViewController如下;

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

where "categories" is the push segue identifier from MainPageViewControllerto CategoriesTableViewController.

其中“categories”是从MainPageViewControllerto的 push segue 标识符CategoriesTableViewController

The program enters the unwindToMainMenufunction but it does not perform the push segue. Any idea how to fix this?

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

Note: I found the same questionbut the answer suggests to change the storyboard structure.

注意:我发现了同样的问题,但答案建议更改故事板结构。

回答by wyu

A bit late to the party but I found a way to do this without using state flags

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

Note: this only works with iOS 9+, as only custom segues support class names prior to iOS9 and you cannot declare an exit segue as a custom segue in storyboards

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

1. Subclass UIStoryboardSegue with UIStoryboardSegueWithCompletion

1. 使用 UIStoryboardSegueWithCompletion 子类 UIStoryboardSegue

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

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

2. Set UIStoryBoardSegueWithCompletion as the class for your exit segue

2. 将 UIStoryBoardSegueWithCompletion 设置为退出转场的类

note: the action for this segue should be unwindToMainMenuto match the original question

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

Select exit segue from storyboardAdd custom class

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

3. Update your unwind @IBAction to execute the code in the completion handler

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

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

Your code will now execute after the exit segue completes its transition

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

回答by Berkan Ercan

I want to provide my own solution to this problem for now. Any further answers are always welcome.

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

I put a boolean variable and viewDidAppear function to MainPageViewController.

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

var fromCamera = false

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

I set fromCamerato truebefore I perform unwind segue from CropViewController. By that way, I perform segue to category screen only if an unwind segue from crop view is performed.

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

回答by Ayush Goel

Taking forward this answer(I only had Objective-C code)

提出这个答案(我只有 Objective-C 代码)

Subclass UIStoryBoardSegue

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

And call this completion block after completion of animations.

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

@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

回答by moride

Taking forward the previous two answers, there is a bit more detail about the objective c version here (I too only had Objective-C code)

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

  1. Subclass UIStoryboardSegue with UIStoryboardSegueWithCompletion

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

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

    }

  1. 使用 UIStoryboardSegueWithCompletion 子类 UIStoryboardSegue

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

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

    }

UIStoryboardSegueWithCompletion.h

UIStoryboardSegueWithCompletion.h

#import <UIKit/UIKit.h>

@interface MyStoryboardSegue : UIStoryboardSegueWithCompletion

@property (nonatomic, copy) void(^completion)();

@end

UIStoryboardSegueWithCompletion.m

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. Set UIStoryBoardSegueWithCompletion as the class for your exit segue
  1. 将 UIStoryBoardSegueWithCompletion 设置为退出 segue 的类

note: the action for this segue should be unwindToMainMenu to match the original question [image showing segue ui][1] [image showing segue ui 2][2]

注意:此转场的操作应为 unwindToMainMenu 以匹配原始问题 [图像显示转场 ui][1] [图像显示转场 ui 2][2]

Select exit segue from storyboard Add custom class

从故事板中选择退出 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];
        };
    }
}

Your code will now execute after the exit segue completes its transition

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

回答by Ron Fessler

I'm guessing the performSegue is not firing because the unwind segue has not yet finished. The only thing I can think of at the moment, is to delay calling the performSegue using dispatch_after. This seems very "hacky" to me though.

我猜 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)
    }
}

回答by Cole

The exit segue IBAction method happens before the actual unwind segue is finished. I had the same issue and resolved it this way (if you don't mind my paraphrasing of your code). It avoids the extra time and animations from relying on ViewDidAppear.

退出转场 IBAction 方法在实际展开转场完成之前发生。我遇到了同样的问题并以这种方式解决了它(如果你不介意我对你的代码的解释)。它避免了依赖 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)
}

Hope this is helpful for anyone else who runs into this and just wants an instantaneous transition!

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

回答by John Rogers

Updated @moride's answer for Swift 5. The transition coordinator is now optional, so we run completion immediately if this is the case.

更新了@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()
        }
    }
}