Использование стека массивов и анимация между UIViewControllers приводит к неожиданному поведению - PullRequest
0 голосов
/ 12 декабря 2018

Использование Swift 4 и Xcode 10.1

Моя цель - использовать стек массивов для отслеживания моих UIViewControllers, когда я анимирую между ними.Я получил большую часть его работы, однако, когда я перехожу ViewController в представление во второй раз, он, кажется, меняет местами с текущим контроллером представления ниже.

Базовая настройка (раскадровка) - это UIViewController, которыйимеет ContainerView (MainContainer) и 4 отдельных ViewControllers (VC1, VC2, VC3, VC4).У каждого VC также есть идентификатор восстановления, чтобы я мог распечатать его и отследить положение в массиве стека.

В начале я отображаю VC1, затем использую кнопки для проверки обработки каждого VC.

Вот код:

@IBOutlet weak var MainContainer: UIView!    
var vc1:UIViewController!
var vc2:UIViewController!
var vc3:UIViewController!
var vc4:UIViewController!
var vcStack = Stack<UIViewController>()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    vc1 = self.storyboard?.instantiateViewController(withIdentifier: "VC1")
    vc2 = self.storyboard?.instantiateViewController(withIdentifier: "VC2")
    vc3 = self.storyboard?.instantiateViewController(withIdentifier: "VC3")
    vc4 = self.storyboard?.instantiateViewController(withIdentifier: "VC4")

    vcStack.push(vc1)
    displayVC(content: vc1!)
}

func displayVC(content: UIViewController) {
    // Works to change VCs - no transition
    self.addChild(content)
    content.view.translatesAutoresizingMaskIntoConstraints = false
    self.MainContainer.addSubview(content.view)

    NSLayoutConstraint.activate([
        content.view.leftAnchor.constraint(equalTo: self.MainContainer.leftAnchor, constant: 0),
        content.view.topAnchor.constraint(equalTo: self.MainContainer.topAnchor, constant: 0),
        content.view.bottomAnchor.constraint(equalTo: self.MainContainer.bottomAnchor, constant: 0),
        content.view.rightAnchor.constraint(equalTo: self.MainContainer.rightAnchor, constant: 0)
        ])

    content.didMove(toParent: self)
}

func slideINTransition(newVC: UIViewController){
    print("slide IN stack newVC: \(newVC.restorationIdentifier ?? "novalue")")
    print("slide IN stack stack top: \(vcStack.top!.restorationIdentifier ?? "novalue")")
    newVC.view.frame = vcStack.top!.view.frame;
    vcStack.top!.view.superview?.insertSubview(newVC.view, aboveSubview: vcStack.top!.view)
    newVC.view.transform = CGAffineTransform(translationX: vcStack.top!.view.frame.size.width, y: 0)

    UIView.animate(withDuration: 0.5,
                   delay: 0.0,
                   options: UIView.AnimationOptions.curveEaseInOut,
                   animations: {
                    newVC.view.transform = CGAffineTransform(translationX: 0, y: 0)
                  },
                   completion:nil// { finished in
                    //self.vcStack.top!.present(newVC, animated: false, completion: nil) //throws an error when uncommented
                //}
                  )
    vcStack.push(newVC)
    for junk in vcStack.array{
        print("slide IN stack: \(junk.restorationIdentifier ?? "novalue")")
    }
}
@IBAction func But_Back_Pressed(_ sender: UIButton) {
    for junk in vcStack.array{
        print("-----back but stack: \(junk.restorationIdentifier ?? "novalue")")
    }
    slideOUTTransition()
}
func slideOUTTransition(){
    print("slideOUT count: \(vcStack.count)")
    if (vcStack.count > 1) {
        let visibleVC = vcStack.pop()
        visibleVC!.view.transform = CGAffineTransform(translationX: 0, y: 0)
        UIView.animate(withDuration: 0.5,
                       delay: 0.0,
                       options: UIView.AnimationOptions.curveEaseInOut,
                       animations: {
                        visibleVC!.view.transform = CGAffineTransform(translationX: visibleVC!.view.frame.size.width, y: 0)
                       },
                       completion: { finished in
                        visibleVC!.dismiss(animated: false, completion: nil)
                       }
                       )
        for junk in vcStack.array{
            print("slideOUT stack: \(junk.restorationIdentifier ?? "novalue")")
        }
        print("BACK pop count: \(vcStack.count)")
    }
}

@IBAction func But_VC1_Pressed(_ sender: UIButton) {
    if vcStack.hasElement(vc1){
        print("Trans vc1 exists - doing nothing")
    }else{
        print("Trans vc1 unique")
        slideINTransition(newVC: vc1)
    }
}
@IBAction func But_VC2_Pressed(_ sender: UIButton) {
    if vcStack.hasElement(vc2){
        print("Trans vc2 exists - doing nothing")
    }else{
        print("Trans vc2 unique")
        slideINTransition(newVC: vc2)
    }
}
@IBAction func But_VC3_Pressed(_ sender: UIButton) {
    if vcStack.hasElement(vc3){
        print("Trans vc3 exists - doing nothing")
    }else{
        print("Trans vc3 unique")
        slideINTransition(newVC: vc3)
    }
}
@IBAction func But_VC4_Pressed(_ sender: UIButton) {
    if vcStack.hasElement(vc4){
        print("Trans vc4 exists - doing nothing")
    }else{
        print("Trans vc4 unique")
        slideINTransition(newVC: vc4)
    }
}

public struct Stack<T> where T: Equatable {
    fileprivate var array = [T]()

    public var isEmpty: Bool {
        return array.isEmpty
    }

    public var count: Int {
        return array.count
    }

    public mutating func push(_ element: T) {
        array.append(element)
    }

    public mutating func pop() -> T? {
        return array.popLast()
    }

    public func hasElement(_ element: T) -> Bool {
        return array.contains(element)
    }

    public var top: T? {
        return array.last
    }
}

Простой тест, который не проходит:

Добавьте VC2, нажав кнопку VC2, и он скользит справа налево по VC1, и VC2 помещается в стек,Нажмите кнопку «Назад», чтобы VC2 скользил назад, слева направо, чтобы снова открыть VC1, и VC2 выталкивается из стека.Пока это работает - только VC1 виден.

Однако, когда я затем нажимаю кнопку VC2 во второй раз, появляется возможность поменяться местами с VC1.VC1 немедленно заменяется на VC2, а затем VC1 скользит слева направо по верху.Каким-то образом это выглядит так, как будто VC2 и VC1 меняются местами перед анимацией.

Также следует отметить - я могу поместить VC2, VC3 и VC4 друг на друга и поместить их в стек, а затем нажать кнопку «Назад», чтобы удалить их изпосмотреть и все работает.Однако после повторного нажатия любого vc происходит перестановка с любым представлением, расположенным непосредственно ниже.

Я отслеживаю массив стека с помощью операторов печати, и он, кажется, работает правильно.Анимации также работают должным образом, поэтому я, должно быть, делаю что-то не так с тем, как я отображаю / добавляю VC ....

Любые идеи, почему каждый VC может быть анимирован в вид, затем удален, но не анимирован в видснова?

1 Ответ

0 голосов
/ 12 декабря 2018

Я думаю, что есть много вещей, которые можно улучшить в отношении содержания контроллера представления (без обид!), Но для решения вашей проблемы сейчас сделайте следующее:

Вместо вызова visibleVC!.dismiss(animated: false, completion: nil) в блоке завершения вашегоslideOUTTransition() (вы ничего не представили, поэтому вам не нужно ничего отклонять) удалите представление из суперпредставления и сбросьте его преобразование:

// visibleVC!.dismiss(animated: false, completion: nil)
visibleVC!.view.removeFromSuperview()
visibleVC!.view.transform = .identity
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...