Подтвердить что ты не робот

Выполните push-сегу после разматывания

Я работаю над приложением камеры, где изображения камеры отображаются в моделях. После того, как я закончил с обрезкой. Я выполняю разматывание до MainPageViewController. (См. Скриншот)

storyboard

Моя функция отключения внутри MainPageViewController выглядит следующим образом:

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

где "категории" - это идентификатор push segue от MainPageViewController до CategoriesTableViewController.

Программа входит в функцию unwindToMainMenu, но не выполняет push-сег. Любая идея, как это исправить?

Примечание. Я нашел тот же question, но ответ предлагает изменить структуру раскадровки.

4b9b3361

Ответ 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
  1. Установить 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