使用Swift 4和Xcode 10.1
我的目标是在我对它们进行动画处理时,使用数组堆栈来跟踪我的UIViewController。 我已经大部分工作了,但是当我第二次将ViewController转换为视图时,它似乎与下面的当前视图控制器交换了位置。
基本设置(故事板)是一个UIViewController,它具有一个ContainerView(MainContainer)和4个单独的ViewController(VC1,VC2,VC3,VC4)。每个VC都有一个restoreId,以便我可以打印它并跟踪堆栈数组中的位置。
首先显示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动画化,然后将其删除,但又不能动画化?
答案 0 :(得分:1)
我认为有很多事情可以使有关视图控制器的约束变得更好(没有违法!),但现在要解决您的问题,请执行以下操作:
与其在您的visibleVC!.dismiss(animated: false, completion: nil)
的完成块中调用slideOUTTransition()
(您没有提供任何内容,所以您不必消除任何内容),而是从超级视图中删除视图并重置其转换: / p>
// visibleVC!.dismiss(animated: false, completion: nil)
visibleVC!.view.removeFromSuperview()
visibleVC!.view.transform = .identity