【问题标题】:Animating view on viewDidAppear not working correctly - SwiftviewDidAppear 上的动画视图无法正常工作 - Swift
【发布时间】:2016-01-03 05:52:52
【问题描述】:

我正在尝试让view 从屏幕中心设置动画,以便在视图加载后 1 秒后离开屏幕。

我遇到的问题是,在 view 在加载时处于原始(正确)位置的一毫秒后,它会捕捉到新位置并动画回到原始位置。

我在viewDidLoad中有以下代码

override func viewDidAppear(animated: Bool) {

    UIView.animateWithDuration(0.7, delay: 1, options: .CurveEaseOut, animations: {
        var loadingViewFrame = self.loadingView.frame
        loadingViewFrame.origin.y += 600

        self.loadingView.frame = loadingViewFrame
        }, completion: { finished in
            print("moved")
    })


}

我已尝试将此代码放入 button 操作中,它工作正常,那么在 viewWillAppear 上制作动画时我应该使用其他方法吗?还是我错过了其他方法?

我已删除所有自动布局约束,因为我读到它们可能会导致一些问题。

我在viewDidAppear 以及viewWillAppearviewDidLoad 中还有其他代码,如果您认为它有用,我可以在这里展示它们,但我已经注释掉了所有这些代码,只留下基本代码并且仍然发生相同的错误。

非常感谢您的帮助。


编辑 1

我已将代码移至viewDidLayoutSubviews 并使用dispatch_once 确保只执行一次。图像仍会从新位置动画到原始位置,但现在图像在加载时有一毫秒内未位于原始位置。

这是我添加的代码

    var token: dispatch_once_t = 0

override func viewDidLayoutSubviews() {
    dispatch_once(&token) {

        UIView.animateWithDuration(0.7, delay: 1, options: .CurveEaseOut, animations: {
            var loadingViewFrame = self.loadingView.frame
            loadingViewFrame.origin.x += 600

            self.loadingView.frame = loadingViewFrame
            }, completion: { finished in
                print("moved")
        })
    }
}

【问题讨论】:

    标签: ios swift animation uiview viewdidappear


    【解决方案1】:

    首先,当您在视图控制器子类中覆盖 viewDidAppear: 时,您需要调用 super.viewDidAppear(animated)

    不幸的是,这个视图控制器对我来说似乎工作得很好,所以肯定有其他事情发生......

    class ViewController: UITableViewController {
        var loadingView: UIView!
    
        override func viewDidLoad() {
                super.viewDidLoad()
    
            loadingView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
            loadingView.backgroundColor = UIColor.redColor()
            loadingView.center = view.center
            view.addSubview(loadingView)
        }
    
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
    
            UIView.animateWithDuration(0.7, delay: 1, options: .CurveEaseOut, animations: {
                var loadingViewFrame = self.loadingView.frame
                loadingViewFrame.origin.y += 600
    
                self.loadingView.frame = loadingViewFrame
            }, completion: nil)
        }
    }
    

    您的问题很可能是因为 layoutSubviews 可能在 viewDidAppear: 之后被调用(我相信这对于 iOS 8 和 iOS 9 是不同的)所以您所做的更改几乎会立即被覆盖。您可以通过在您的UIViewController 子类中覆盖viewDidLayoutSubviews 并设置断点viewDidLoadviewWillAppear:viewDidAppear:viewDidLayoutSubviews 来确认这一点,以查看它们发生的顺序。

    您可以做的一件事是使用带有once_tokendispatch_once 块,这是您的类的属性来执行viewDidLayoutSubviews 中的动画。这将确保在初始视图布局发生后,每个类的实例都会执行一次动画。这可能就是您要找的。​​p>

    如果您可以提供更多视图控制器代码或 github 链接,我或许可以为您提供一个更好、更少潜在的 hacky 的关于正在发生的事情的答案。

    【讨论】:

    • 非常感谢您的回复。我之前实际上尝试将动画代码放在viewDidLayoutSubviews 中,但它被调用了几次并且变得非常紧张。现在我已经按照您的建议添加了dispatch_once,它只执行一次,但它仍然是从新位置到原始位置,但是它在开始时不再有很短的时间在正确的位置。
    • 我对 swift 和一般编码仍然很陌生,所以我将使用添加到 viewDidLayoutSubviews 的代码更新原始问题。如果我做错了什么,请告诉我,如果没有,还有什么可能导致这个问题。谢谢
    • 我现在所做的是将原始位置设置为屏幕外,以便图像从原始位置开始,但应该是新位置(在屏幕上)并动画到应该是新位置位置,但编码为原始位置(屏幕外)......如果有意义的话。
    • 这似乎是一种可怕的做法,我可以看到它会导致进一步的问题。你怎么看?必须有更好的方法来做到这一点。任何建议将不胜感激
    • 是的,如果你不小心的话,这肯定会导致问题。通常,您可能不想在 viewDidLayoutSubviews 中做太多事情,因为它可以被多次调用。我只是在建议一种策略,当视图第一次出现在屏幕上时,您可以使用它来让某事发生一次。我可能让你误入歧途,因为它是深夜,我无法打开 xcode。您的问题可能仅仅是因为您没有在方法中调用 super.viewDidAppear。我会自己尝试一下,看看能否为您找到更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 2014-10-01
    • 2017-12-18
    相关资源
    最近更新 更多