UIView.animate 未在 PHPhotoLibrary.shared().performChanges 中执行
UIView.animate not executed in PHPhotoLibrary.shared().performChanges
我一整天都在处理以下代码,但根本找不到问题所在。我想保存视频并在完成后使某些按钮或微调器(消失)出现。所有按钮都在 viewDidLoad
中设置,可以说是存在的(它们是可选的,因此也是可选的链接)。我的问题是 if
子句中的动画永远不会执行。只是有时如果我在每一行代码之前放置断点,它就会起作用,这真的让我感到奇怪(顺便说一句:断点并不表示任何异常)。此外,如果我将 if success2 == true
的代码替换为 else
(if 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
}
}
})
}
})
我会 post 我的评论作为一个更好的解释的答案。
要使 UIView
动画正常工作,它们必须在主线程上使用(就像所有其他 UIKit 东西一样!)。
From the documentation 对于 PHPhotoLibrary
,Apple 声明:
Photos executes both the change block and the completion handler block on an arbitrary serial queue. To update your app’s UI as a result of a change, dispatch that work to the main queue.
这意味着您应该期望处理来自 Apple 的响应,就像它来自主线程以外的其他地方一样。因此,一个简单的解决方法是调用:
DispatchQueue.main.async {}
并将其包裹在您要执行 UIKit 内容的代码周围。
Apple 不在主线程上工作的原因是因为他们正在做的工作可能很重要,而且它会占用主线程,这会使您的 UI 迟钝和无响应.
我还建议对您的代码进行一些小调整,以使其更易于阅读。在完成处理程序中,我会将代码提取到一个函数中,然后您所要做的就是将该函数调用包装在一个 DispatchQueue.main.async {}
调用中,而不是将您想要设置动画的整个代码块包装起来。
另外不要忘记使用 Swift 的最佳语言功能之一:optional chaining。这意味着你不必在尝试使用它之前检查它是否存在,如果它不存在它就会退出。所以你可以安全地做这样的事情:
checkButton?.alpha = 1
我一整天都在处理以下代码,但根本找不到问题所在。我想保存视频并在完成后使某些按钮或微调器(消失)出现。所有按钮都在 viewDidLoad
中设置,可以说是存在的(它们是可选的,因此也是可选的链接)。我的问题是 if
子句中的动画永远不会执行。只是有时如果我在每一行代码之前放置断点,它就会起作用,这真的让我感到奇怪(顺便说一句:断点并不表示任何异常)。此外,如果我将 if success2 == true
的代码替换为 else
(if 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
}
}
})
}
})
我会 post 我的评论作为一个更好的解释的答案。
要使 UIView
动画正常工作,它们必须在主线程上使用(就像所有其他 UIKit 东西一样!)。
From the documentation 对于 PHPhotoLibrary
,Apple 声明:
Photos executes both the change block and the completion handler block on an arbitrary serial queue. To update your app’s UI as a result of a change, dispatch that work to the main queue.
这意味着您应该期望处理来自 Apple 的响应,就像它来自主线程以外的其他地方一样。因此,一个简单的解决方法是调用:
DispatchQueue.main.async {}
并将其包裹在您要执行 UIKit 内容的代码周围。
Apple 不在主线程上工作的原因是因为他们正在做的工作可能很重要,而且它会占用主线程,这会使您的 UI 迟钝和无响应.
我还建议对您的代码进行一些小调整,以使其更易于阅读。在完成处理程序中,我会将代码提取到一个函数中,然后您所要做的就是将该函数调用包装在一个 DispatchQueue.main.async {}
调用中,而不是将您想要设置动画的整个代码块包装起来。
另外不要忘记使用 Swift 的最佳语言功能之一:optional chaining。这意味着你不必在尝试使用它之前检查它是否存在,如果它不存在它就会退出。所以你可以安全地做这样的事情:
checkButton?.alpha = 1