2016-12-10 4 views
0
@IBAction func sendSweet(sender: UIBarButtonItem) { 

    var inputTextField: UITextField? 
    let alert = UIAlertController(title: "New sweet", message: "Enter a sweet", preferredStyle: .alert) 
    alert.addTextField { (textField: UITextField) in 
     textField.placeholder = "Your sweet" 
     inputTextField = textField 
    } 

    let sendAction = UIAlertAction(title: "Send", style: .default, handler: { 
     [weak self] (alertAction: UIAlertAction) in 
     guard let strongSelf = self else { return } 

     if inputTextField?.text != "" { 
      let newSweet = CKRecord(recordType: "Sweet") 
      newSweet["content"] = inputTextField?.text as CKRecordValue? 

      let publicData = CKContainer.default().publicCloudDatabase 
      publicData.save(newSweet, completionHandler: { 
       (record: CKRecord?, error: Error?) in 

       if error == nil { 
        // we want ui code to dispatch asychronously in main thread 
        DispatchQueue.main.async { 
         strongSelf.tableView.beginUpdates() 
         strongSelf.sweets.insert(newSweet, at: 0) 
         let indexPath = IndexPath(row: 0, section: 0) 
         strongSelf.tableView.insertRows(at: [indexPath], with: .top) 
         strongSelf.tableView.endUpdates() 
        } 
       } else { 
        if let error = error { 
         print(error.localizedDescription) 
         return 
        } 
       } 
      }) 
     } 
    }) 

    alert.addAction(sendAction) 
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) 
    present(alert, animated: true, completion: nil) 

} 

私はこのコールバック地獄を持って、私はネストされたコールバックの強い基準サイクル

  1. コールバック地獄の最上部にある[weak self] & guard let strongSelfはGCDのを介してすべての強い参照サイクルを防ぐん知りたいです非同期コールバック。私は、コールバックの中で参照するオブジェクトがdeinitであれば正常に参照することができますが、それは強い参照サイクルを持たないための良い兆候を意味しています、それはまだ本当ですか?

  2. この種のコールバックを防ぐにはどうすればいいですか?私が見逃してしまった資料やトピックに私を導くことができますか? javascriptの約束の連鎖構文のようなものは何ですか?

答えて

1

私が見る限り、保持サイクルはないので、弱化する必要はありませんself。あなたは確かにすべてのブロックでそれを守るために行うことができます。

インスタンス(self)にいずれのクロージャも参照されていないため、保持サイクルはありません。特にsendActionには、sendSweet関数の中でsendActionが宣言されています。

class MyView: UIView { 
    let str = "some variable to have somsthing to use self with" 

    func foo() { 
     let ba = { 
      // no problem. The instance of MyView (self) does not hold a (strong) reference to ba 
      self.str.trimmingCharacters(in: CharacterSet.alphanumerics) 
     } 

     ba() 
    } 
} 

あなたは、インスタンスのプロパティとしての機能のlet sendAction = ...外を移動したい場合、あなたはかかわらず、基準周期を持っているでしょう。この場合、インスタンス(self)はsendActionに強いrefrenceを有するであろうとsendActionクロージャはインスタンス(self)への強い参照を有するであろう:

自己< - > {自己。 ...}別名sendAction。あなたがやったように、クロージャ内weak ifying selfによる悪循環を断ち切るために持っている。この場合

class MyView: UIView { 
    let str = "asd" 
    // Problem. 
    // The instance of MyView (self) does hold a (strong) reference to ba ... 
    let ba:() -> Void 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     ba = {  
      // ... while ba holds a strong reference to the instance (self)   
      self.str.trimmingCharacters(in: CharacterSet.alphanumerics) 
     } 
    } 

    func foo() { 
     ba() 
    } 
} 

。コールバック地獄のこの種のを防止するための方法


、あなたはいくつかの読み物

アウトDispatchGroup秒に私を導くことができます。

Apple Documentation

+0

この、基準周期のみを私が読ん別のブログ記事を思い出させますオブジェクトの階層で2つの方向で参照しようとしたときに発生しますが、一方向では参照しません。 –

+0

「サイクル」の定義。 – shallowThought

0

は私の問題#2

https://github.com/duemunk/Async

例にかなりきちんとした解決策を見つけたがスニペット:

Async.userInitiated { 
    return 10 
}.background { 
    return "Score: \($0)" 
}.main { 
    label.text = $0 
} 
関連する問題