swift闭包的循环引用

例子是一个简单通讯录,列表界面点击添加联系人按钮跳到添加界面,添加联系人后返回到列表界面ListVC,但是添加界面DetailVC没有释放

//
//  ListVC.swift
//  contract
//
//  Created by targetcloud on 2017/2/11.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

class ListVC: UITableViewController {
    
    var personDataSource=[Person]()

    override func viewDidLoad() {
        super.viewDidLoad()

        loadData { (list) in
            print(list)
            self.personDataSource += list
            self.tableView.reloadData()
        }
    }
    
    private func loadData(completion:@escaping (_ listblock: [Person])->()) ->() {
        DispatchQueue.global().async {
            print("正在努力加载中...")
            Thread.sleep(forTimeInterval: 2)
            var arrayM :[Person] = [Person]()
            for i in 0..<20{
                let p = Person()
                p.name = "name - \(i)\(arc4random_uniform(100))"
                p.phone = "138"+String(format: "%08d", arc4random_uniform(100000000))
                p.title = "Boss"
                arrayM.append(p)
            }
            DispatchQueue.main.async {
                completion(arrayM)
            }
        }
    }

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

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
        cell.textLabel?.text = personDataSource[indexPath.row].name
        cell.detailTextLabel?.text = personDataSource[indexPath.row].phone
        return cell
    }
    
    
    @IBAction func newClick(_ sender: Any) {
        performSegue(withIdentifier: "new2detail", sender: nil)
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        performSegue(withIdentifier: "list2detail", sender: indexPath)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let vc = segue.destination as! DetailVC
        if let indexPath = sender as? IndexPath{
            vc.person = personDataSource[indexPath.row]
            vc.completionBlock = {
                self.tableView.reloadRows(at: [indexPath], with: .automatic)
            }
        }else{//new person
            vc.completionBlock = {
                guard let p = vc.person else {
                    return
                }
                self.personDataSource.insert(p, at: 0)
                self.tableView.reloadData()
            }
        }
    }
}

//
//  DetailVC.swift
//  contract
//
//  Created by targetcloud on 2017/2/11.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

class DetailVC: UITableViewController {

    var person : Person?
    var completionBlock : (()->())?
    
    @IBOutlet weak var nameTF: UITextField!
    @IBOutlet weak var titleTF: UITextField!
    @IBOutlet weak var phoneTF: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if person != nil{
            nameTF.text = person?.name
            phoneTF.text = person?.phone
            titleTF.text = person?.title
        }
    }

    @IBAction func saveClick(_ sender: Any) {
        if person == nil{//new person
            person = Person()
        }
        
        person?.name = nameTF.text
        person?.phone = phoneTF.text
        person?.title = titleTF.text
        completionBlock?()
        _=navigationController?.popViewController(animated: true)
    }

}

以下这段代码有问题

vc.completionBlock = {
                guard let p = vc.person else {
                    return
                }
                self.personDataSource.insert(p, at: 0)
                self.tableView.reloadData()
            }


正确写法应该是

            vc.completionBlock = {[weak vc] in
                guard let p = vc?.person else {
                    return
                }
                self.personDataSource.insert(p, at: 0)
                self.tableView.reloadData()
            }

原因:vc对 completionBlock有引用,闭包代码中又引用了vc,造成循环引用,所以使用前,要加 [weak vc] in,用到vc的地方后面加?,即vc?



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值