UIView.animate未在PHPhotoLibrary.shared()。performChanges中执行

时间:2017-07-15 16:08:43

标签: ios swift uiviewanimation

我现在一整天都在处理以下代码,根本无法找到问题。我想保存视频,完成后会出现某些按钮或旋转器(dis-)。所有按钮都在viewDidLoad中设置,因此可以说存在(它们是可选项,因此也是可选链接)。我的问题是if子句中的动画永远不会被执行。有时候,如果我在每行代码之前放置断点,那么它确实让我感到奇怪(顺便说一句:断点并不表示任何异常)。此外,如果我将if success2 == true的代码替换为elseif success2 == false)的代码,则可以正常工作(在弹出警报后)。我差不多四次检查我的代码,只是找不到我做错了什么。有谁知道可能是什么问题以及如何解决?

对于巨大的代码块抱歉:

PHPhotoLibrary.shared().performChanges({
    if let assetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url) {
        let assetCollectionChangeRequest = PHAssetCollectionChangeRequest(for: albumAssetCollection)
        let enumeration: NSArray = [assetChangeRequest.placeholderForCreatedAsset!]
        assetCollectionChangeRequest?.addAssets(enumeration)
    }
}, completionHandler: { (success2: Bool, error2: Error?) in
    if success2 == true {
        // prompt that the video has been saved
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            if let checkButton = self.checkButton, let saveSpinner = self.saveSpinner, let resetButton = self.resetButton {
                saveSpinner.alpha = 0
                checkButton.alpha = 1
                resetButton.alpha = 1
            }
        }) { (completed: Bool) in
            if completed == true {
                if let saveSpinner = self.saveSpinner {
                    saveSpinner.stopAnimating()
                    self.timeLimitReached = false
                    self.changeClipsCount()
                }
                UIView.animate(withDuration: 0.5, delay: 3, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                    if let checkButton = self.checkButton, let saveButton = self.saveButton {
                        checkButton.alpha = 0
                        saveButton.alpha = 1
                    }
                }) { (completed: Bool) in }
            }
        }
    } else {
        // prompt that the video has not been saved
        let alertController = UIAlertController(title: "Something failed!", message: "The video could not be saved.", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(okAction)
        self.present(alertController, animated: true, completion: {
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                if let saveButton = self.saveButton, let saveSpinner = self.saveSpinner {
                    saveButton.alpha = 1
                    saveSpinner.alpha = 0
                }
            }) { (completed: Bool) in
                if let saveSpinner = self.saveSpinner {
                    saveSpinner.stopAnimating()
                    self.timeLimitReached = false
                }
            }
        })
    }
})

1 个答案:

答案 0 :(得分:2)

我将发表评论作为答案,并提供一些更好的解释。

要使UIView动画起作用,必须在主线程上使用它们(就像所有其他UIKit一样!)。

对于PHPhotoLibrary

From the documentation,Apple表示:

  

Photos会在任意串行队列上执行更改块和完成处理程序块。要根据更改更新应用的UI,请将该工作分配到主队列。

这意味着您应该期望处理来自Apple的响应,就好像它来自主线程之外的某个地方。因此,一个简单的解决方法是致电:

DispatchQueue.main.async {}并将代码包围在您想要执行UIKit的代码中。

Apple不在主线程上工作的原因是因为他们正在做的工作可能很重要,并且会占用主线程,这会使你的UI缓慢且无响应。 / p>

我还建议您对代码进行一些小调整,以便更容易阅读。在完成处理程序中,我将代码提取到一个函数中,然后你所要做的就是在DispatchQueue.main.async {}调用中包装该函数调用,而不是你想要动画的整个代码块。

另外,请不要忘记使用Swift最好的语言功能之一:optional chaining。这意味着在尝试使用它之前你不必检查是否存在某些东西,如果它不存在它就会拯救它。所以你可以安全地做这样的事情:

checkButton?.alpha = 1