2017-07-15 42 views
0

我一直在努力,現在整天下面的代碼根本無法發現問題。我想保存視頻,完成後會顯示某些按鈕或旋鈕(dis-)。所有的按鈕設置在viewDidLoad,所以說存在(他們是可選項,因此也是可選的鏈接)。我的問題是if子句中的動畫永遠不會執行。有時候,如果我在每一行代碼之前放置斷點,它的作用真的讓我感到奇怪(順便說一句:斷點並不表示任何異常)。此外,如果我將if success2 == true的代碼替換爲elseif success2 == false)的代碼,它會工作(在彈出警報之後)。我幾乎四倍檢查我的代碼,只是無法找到我做錯了什麼。有沒有人有一個想法,可能是什麼問題以及如何解決?UIView.animate()。performChanges

對不起,我的代碼塊巨大:

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

completionHandler是由蘋果代碼在主線程或後臺線程上調用的嗎? 另外,作爲一個側面說明,如果你使用可選的鏈接,你不需要'如果讓checkButton = checkButton',你可以使用'checkButton?阿爾法= 1' –

+0

這不是在主線程!然而,我仍然不確定爲什麼會出現這種情況(解釋會非常感謝)......將'if'的所有代碼放在'DispatchQueue.main.async {}'中,現在它可以工作(在檢查它之後在使用'Thread.isMainThread'的主線程中)!非常感謝! – Moritz

+1

我已經回答了更好的解釋:) –

回答

1

我會後與一點點更好的解釋回答我的意見。

對於UIView動畫工作,他們必須在主線程上使用(就像所有其他的UIKit的東西!)。

From the documentationPHPhotoLibrary,蘋果狀態:

照片執行這兩個變化塊上的任意串行隊列完成處理塊。要通過更改更新應用的UI,請將該工作分派給主隊列。

這意味着您應該期待處理來自Apple的響應,就好像它來自主線程以外的某個位置。因此,一個簡單的辦法,這是調用:

DispatchQueue.main.async {},敷周圍,你想要做的UIKit東西的代碼。

蘋果公司在主線程中沒有做好工作的原因是因爲他們正在做的工作可能會很重要,並且會佔用主線程,從而導致您的用戶界面緩慢且無響應。

我也建議一些小的調整,以你的代碼只是爲了使其更易於閱讀。在完成處理程序中,我會將代碼提取到一個函數中,然後您只需要在調用DispatchQueue.main.async {}時將該函數調用包裝起來,而不是整個要生成動畫的代碼塊。

也不要忘了利用斯威夫特的最好的語言特點之一:optional chaining。這意味着你不必在使用它之前檢查是否存在,如果它不存在,它就會被釋放。所以你可以安全地做這樣的事情:

checkButton?.alpha = 1 
相關問題