例子是一个简单通讯录,列表界面点击添加联系人按钮跳到添加界面,添加联系人后返回到列表界面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?