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
Perform push segue after an unwind 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
. (请看截图)
My unwind function inside MainPageViewController
is as follows;
我里面的 unwind 功能MainPageViewController
如下;
@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
self.performSegueWithIdentifier("Categories", sender: self)
}
where "categories" is the push segue identifier from MainPageViewController
to CategoriesTableViewController
.
其中“categories”是从MainPageViewController
to的 push segue 标识符CategoriesTableViewController
。
The program enters the unwindToMainMenu
function 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 unwindToMainMenu
to match the original question
注意:此 segue 的操作应该是unwindToMainMenu
匹配原始问题
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 fromCamera
to true
before 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
为. 通过这种方式,只有在从裁剪视图执行展开转场时,我才会执行转场到类别屏幕。true
CropViewController
回答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 代码)
Subclass UIStoryboardSegue with UIStoryboardSegueWithCompletion
class UIStoryboardSegueWithCompletion: UIStoryboardSegue { var completion: (() -> Void)?
override func perform() { super.perform() if let completion = completion { completion() } }
}
使用 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
- Set UIStoryBoardSegueWithCompletion as the class for your exit segue
- 将 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()
}
}
}