2017-06-23 84 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存活。因此,因为它们互相引用,它们都不能正确释放。 - >内存泄漏

所以我们可以得出结论,自我必须弱或无主。对于这个例子中的所有意图和目的,它们都完全一样。它们都通过消除闭合保持自我活力的能力来达到“打破保留周期”的目的。那么你会问自己谁会释放自己?你的关闭不关心。但在你的关闭之外思考。你的闭包被你的TableViewController调用,所以既然没有奇怪的事情发生在这里,我们可以安全地假设,如果显示了一个警告,它必须明确地显示在你的TableViewController上。所以一旦你关闭了警报或其他任何东西,你的TableViewController将继续照常运作。尽管你会解雇你的TableViewController,但self会被释放(因为闭包被称为无主),但是到目前为止,没有办法显示这个alert。但是,如果你做了一些奇怪的事情,使得你的TableViewController被解散,但仍然显示警报,那么一旦用户“提交”你的应用程序将崩溃。因为通过声明你的变量是无主的,你基本上对你的封闭做出承诺,即它不必担心自我实体,因为只要你的封闭还活着,它就一直存在。

+0

因此,基本上如果我们不放弃无主或弱,封闭内的属性会受外面变化的影响?或者他们只是需要解除分配的目的...另外,viewController的所有属性都有自己的引用,所以它们如何释放。 –

+0

对不起,我很笨,我尽我所能。 –

+0

你在搅拌东西。无主或弱与外界修改无关。 OK,首先,括号[属性]内的东西不会受外面发生的事情影响。其次,为了取消分配目的,需要软弱无主。避免保留周期。第三,viewController的所有属性都由viewController本身保存,即“Self”。当viewcontroller被解除分配时,它们被释放,当你解雇它时会发生这种情况。这与封闭无关,你只需确保封闭仅在VC存活时使用。 – Pochi

0

检查了这一点。我创建了两个同类的对象。其中一个引用了一个保留自身的闭包,所以即使创建该闭包的函数超出了范围,该对象和闭包仍然保留在彼此之中,并且永远不会被释放。第二个对象的闭包有一个对该对象的弱引用,所以当对象创建函数超出作用域时,引用计数为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