2017-06-23 7 views
0

私はクロージャがデータをキャプチャするという概念を理解していません。データが破壊されない方法を示すクロージャを使用してサンプルコードを書くことはできますか?私は既にAppleのドキュメントを読んでいます。そして、また、どのように...閉鎖の違いを作る「所有されていない」と「弱い私たちは、明示的に物事を割り当て解除されていない場合は、ここで所有されていない作業を行う方法をクロージャはどのようにデータをキャプチャしますか?

class TableViewController: UITableViewController { 

var allWords = [String]() 
var usedWords = [String]() 


override func viewDidLoad() { 
    super.viewDidLoad() 

    if let allWordsPath = Bundle.main.path(forResource: "start", ofType: "txt"){ 

     if let startWords = try? String(contentsOfFile: allWordsPath){ 

      allWords = startWords.components(separatedBy: "\n") 

     }else{ 

      allWords = ["Cake"] 
     } 

     startGame() 
    } 

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Make Word", style: .plain, target: self, action: #selector (makeWord)) 
} 

func startGame(){ 

    allWords = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: allWords) as! [String] 
    title = allWords[0] 
    usedWords.removeAll(keepingCapacity: true) 

} 

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return usedWords.count 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath) 
    cell.textLabel?.text = usedWords[indexPath.row] 
    return cell 

} 


func makeWord() { 

    let ac = UIAlertController(title: "Add Word", message: nil, preferredStyle: .alert) 
    ac.addTextField(configurationHandler: nil) 


    let submit = UIAlertAction(title: "Submit", style: .default){ [unowned self,ac] 

     (action: UIAlertAction!) in 
     let answer = ac.textFields?[0] 
     self.submit(answer: (answer?.text)!) 

     } 

    ac.addAction(submit) 
    present(ac,animated: true) 
} 


var number = 10 
func submit(answer: String){ 
    usedWords.append(answer) 
    tableView.reloadData() 

} 

..

+0

http://alisoftware.github.io/swift/closures/2016/07/25/closure-capture-1/ – Pochi

+0

私は彼の例を理解していません。 –

+0

私の答えをチェックしてください。 Btwクロージャでは、データが破壊されることはありません。彼らは単に、データの処理方法と破壊された場合の対処方法を指定することができます。その変数が "弱い"として設定されていることを完全に有効にして、クロージャ内でそれを単にチェックします。 – Pochi

答えて

0

あなたは最初の検索すべきん強い、弱い、無所属の違い。それについてはここに答えがたくさんあります。

とにかく、この特定の場合には:

あなたの閉鎖は、このコードを持っています

[unowned self,ac] 

これは "キャプチャリスト" と呼ばれています。ブロックが作成されたときに値によって「取り込まれる」べきものを示します。 (ここで指定しないで、ブロックの後のどこかで値を変更すると、ブロック内の値も変更されます)。

自己が所有されていないと割り当てを解除する必要はありません理由は、所有されていない手段理由:

「この変数のメモリ管理を心配しないでください、それは常に の値を持つことになります閉鎖の継続時間」

したがって、所有していない自己に戻ると、閉鎖から自己変数が弱いまたは所有されていないと宣言しなければならない理由は、保持サイクルを作成しなければならないからです。何かがそれを参照している限り、物事を解約することはできません。だから、この場合、あなたのTableViewControllerはあなたのクロージャーを生かしておき、クロージャーはあなたのTableViewControllerを生かしています。だから彼らはお互いを参照しているので、それらのどれも適切に割り当て解除できません。 - >メモリリーク

私たちは、自己が弱い、または所有されていないと結論づけることができます。この例の意図と目的はまったく同じです。彼らはどちらも閉鎖が自己を生かし続ける能力を取り除くことによって「保持サイクルを破る」目的に役立ちます。だから、あなたは自分でdeallocを聞くでしょうか?あなたの閉鎖は気にしません。しかし、あなたの閉鎖の外で考える。あなたのクロージャはあなたのTableViewControllerによって呼び出されているので、ここでは奇妙なことは起こっていないので、警告が表示されていれば、TableViewController上に確実に表示する必要があります。だから一旦警告を消したら、TableViewControllerはいつものように動作します。 1つはあなたのTableViewControllerを却下しますが、selfは解放されません(閉鎖は未所有のものとしてそれを参照しているので)。しかし、この時点では警告が表示されません。しかし、アラートが表示されている間にTableViewControllerを終了させる奇妙なことを行うと、ユーザーが「提出する」とアプリがクラッシュします。あなたの変数を宣言することによって、クロージャが生きている限り、常に存在するように、あなたは自分のエンティティについて心配する必要がないということを、あなたのクロージャに基本的に約束しました。

+0

基本的に未所有者や弱者を置かないと、クロージャー内のプロパティは外部の変更の影響を受けますか?または、それらは目的を解放するためにのみ必要です...また、viewControllerのすべてのプロパティは自身への参照を持っていますので、どのようにそれらの割り当てを解除しますか? –

+0

申し訳ありません私は私のベストを試して私はダムです。 –

+0

あなたはものを混在させています。 UnownedまたはWeakは、外部で修正されているかどうかに関係しません。まずは、大括弧の中にあるものは外で起こっているものの影響を受けません。第二に、割り当てを解除するために弱く、無所属が必要です。第3に、viewControllerのすべてのプロパティは、ViewController自体、つまり「Self」によって生きています。ビューコントローラの割り当てが解除されると、ビューコントローラの割り当てが解除されます。これはクロージャーとは何の関係もなく、VCが生きている間のみクロージャーが使用されるようにする必要があります。 – Pochi

0

これをチェックしてください。私は同じ種類の2つのオブジェクトを作成しています。 1つは、それ自身を保持するクロージャへの参照を持っているため、それを作成した関数が範囲外になっても、オブジェクトとクロージャは互いに保持され、決して解放されません。 2番目のオブジェクトのクロージャはオブジェクトへの弱い参照を持ちます。オブジェクト作成関数が有効範​​囲外になると、参照カウントは0になり、解放されるとクロージャも解放されます。

import UIKit 
import XCPlayground 

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 

class B { 

    deinit { 
     print("\(name) deinit") 
    } 

    var name: String 

    init(name: String) { 
     self.name = name 
    } 
    var zort: (() ->())? 

    func someMethod() { 
     print("") 
    } 
} 

func createStuffThatNeverGoesAway() { 

    var b: B = B(name: "bad"); 
    b.zort = { 
     b.someMethod() 
    } 
} 

func createStuffThatGoesAway() { 

    var b: B = B(name: "good"); 
    b.zort = { [weak b] in 
     b?.someMethod() 
    } 
} 

createStuffThatNeverGoesAway() 
createStuffThatGoesAway() 

出力:

good deinit 
関連する問題