swift闭包的功能很强大。如果block不在当前方法执行,就用一个属性记录它,在需要的时候调用这个属性就可以了。
定义闭包属性:
EmoticonView.swift
/// 选中表情回调
private var selectedEmoticonCallBack: (_ emoticon: Emoticon)->()
如果闭包没有设置为可选项,就需要自定义构造函数创建闭包属性:
先记录闭包属性,再进行接下来的设置
EmoticonView.swift
// MARK: - 构造函数
init(selectedEmoticon: @escaping (_ emoticon: Emoticon)->()) {
// 记录闭包属性
selectedEmoticonCallBack = selectedEmoticon
// 调用父类的构造函数
var rect = UIScreen.main.bounds
rect.size.height = 226
super.init(frame: rect)
backgroundColor = UIColor.white
setupUI()
// 滚动到第一页
let indexPath = NSIndexPath(item: 0, section: 1)
DispatchQueue.main.async {
self.collectionView.scrollToItem(at: indexPath as IndexPath, at: .left, animated: false)
}
}
设置闭包内容
ViewController.swift
/// 表情键盘视图
private lazy var emoticonView: EmoticonView = EmoticonView { [weak self] (emoticon) -> () in
//闭包里面出现self小心循环引用
self?.insertEmoticon(em: emoticon)
// self?.textView.text = emoticon.chs
}
/// 插入表情符号
/// - parameter em: 表情模型
func insertEmoticon(em: Emoticon) {
textView.text = em.chs
}
传递参数,执行回调:
EmoticonView.swift
//MARK: - 代理方法
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// print(indexPath)
// 获取表情模型
let em = packages[indexPath.section].emoticons[indexPath.item]
// 执行`回调`
selectedEmoticonCallBack(em)
}
循环引用问题
(self)控制器强引用emoticonView----emoticonView里面定义闭包属性-----VC强引用闭包
闭包强引用self
形成循环引用问题,解决:[weak self]
class ViewController: UIViewController {
/// 表情键盘视图
private lazy var emoticonView: EmoticonView = EmoticonView { [weak self] (emoticon) -> () in
//闭包里面出现self小心循环引用
self?.insertEmoticon(em: emoticon)
// self?.textView.text = emoticon.chs
}
...................}
测试循环引用问题:
在当前控制器写:
deinit {
print("888")
}
在当前控制器之前,加上navigationController,来测试