Выполните push-сегу после разматывания
Я работаю над приложением камеры, где изображения камеры отображаются в моделях. После того, как я закончил с обрезкой. Я выполняю разматывание до MainPageViewController
. (См. Скриншот)
![storyboard]()
Моя функция отключения внутри MainPageViewController
выглядит следующим образом:
@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
self.performSegueWithIdentifier("Categories", sender: self)
}
где "категории" - это идентификатор push segue от MainPageViewController
до CategoriesTableViewController
.
Программа входит в функцию unwindToMainMenu
, но не выполняет push-сег. Любая идея, как это исправить?
Примечание. Я нашел тот же question, но ответ предлагает изменить структуру раскадровки.
Ответы
Ответ 1
Немного поздно, но я нашел способ сделать это без использования флагов состояния
Примечание: это работает только с iOS 9+, так как только пользовательские segues поддерживают имена классов до iOS9, и вы не можете объявить выход segue как пользовательский segue в раскадровки
1. Подкласс UIStoryboardSegue с UIStoryboardSegueWithCompletion
class UIStoryboardSegueWithCompletion: UIStoryboardSegue {
var completion: (() -> Void)?
override func perform() {
super.perform()
if let completion = completion {
completion()
}
}
}
2. Установите UIStoryBoardSegueWithCompletion как класс для вашего выхода segue
Примечание: действие для этого сеанса должно быть unwindToMainMenu
в соответствии с исходным вопросом
![Добавить пользовательский класс]()
3. Обновите свой unind @IBAction, чтобы выполнить код в обработчике завершения
@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
if let segue = segue as? UIStoryboardSegueWithCompletion {
segue.completion = {
self.performSegueWithIdentifier("Categories", sender: self)
}
}
}
Теперь ваш код будет выполняться после завершения завершения segue
Ответ 2
Я хочу предоставить собственное решение этой проблемы на данный момент. Любые дальнейшие ответы всегда приветствуются.
Я ставлю логическую переменную и функцию viewDidAppear на MainPageViewController
.
var fromCamera = false
override func viewDidAppear(animated: Bool) {
if fromCamera {
self.performSegueWithIdentifier("categorySelection", sender: self)
self.fromCamera = false
}
}
Я установил fromCamera
в true
, прежде чем выполнять разматывание с CropViewController
. Таким образом, я выполняю segue на экране категории только в том случае, если выполняется размотка segue из вида посева.
Ответ 3
Я предполагаю, что performSegue не стреляет, потому что unind segue еще не закончен. Единственное, о чем я могу думать в данный момент, это отсрочить вызов функции выполнения с помощью dispatch_after
. Это кажется мне очень "взломанным".
@IBAction func unwindToMainMenu(segue: UIStoryboardSegue) {
dispatch_after(1, dispatch_get_main_queue()) { () -> Void in
self.performSegueWithIdentifier("Categories", sender: self)
}
}
Ответ 4
Взяв этот ответ (у меня был только код 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
Ответ 5
Выходной метод 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)
}
Надеюсь, это полезно для всех, кто сталкивается с этим и просто хочет мгновенного перехода!
Ответ 6
Взяв предыдущие два ответа, здесь будет немного больше информации о объектной версии c (у меня тоже был код Objective-C)
-
Подкласс UIStoryboardSegue с UIStoryboardSegueWithCompletion
класс UIStoryboardSegueWithCompletion: UIStoryboardSegue { var complete: (() → 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
- Установить UIStoryBoardSegueWithCompletion как класс для вашего выхода segue
note: действие для этого segue должно быть отменено для Moneu, чтобы соответствовать исходному вопросу
[изображение, показывающее segue ui] [1]
[изображение, показывающее segue ui 2] [2]
Выберите exit 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