解决Swift中callback循环引用 - Delegated(Library)
文章目录
- 前言
- 使用示例
- 一般闭包示例
- Delegated 示例
- 源码解析
- 示例Demo
- 示例Demo地址
前言
在Swift中我们使用闭包(Callback)的时候经常要写 [weak self] or [unowned self].
而且你不写, 系统也不会提示你, 这就很容易出现循环引用. ( /(ㄒoㄒ)/~~ 表示本人已经忘记无数次了. )
所以为了避免这种情况, 自然而然就有了这个库 Delegated .
使用示例
一般闭包示例
// 声明
typealias XQCallback = (String) -> ()
private var callback: XQCallback?
// 调用闭包
callback(str)// 外部给闭包赋值
self.callback { [unowned self] (value) inprint(self, value)
}
Delegated 示例
// 声明, 并创建结构体 <inputValue, outputValue>
// inputValue: 调用闭包传出去的值
// outputValue: 闭包内return出来的值
var callback = Delegated<String, Void>.init()
// 调用闭包
callback.call("inputValue")// 外部给闭包赋值
callback.delegate(to: self) { (self, inputValue) inprint(self, inputValue)
}
使用起来, 和原来的闭包写的差不多, 但是这边是把 self 作为参数传进去, 避免了忘写的尴尬.
源码解析
整个库就一个文件, 而且代码很少, 我们一个一个方法来解析.
public struct Delegated<Input, Output> {// 赋值闭包, 无需自己写weak// !!!这个是主要方法, 看明白这个就可以了public mutating func delegate<Target : AnyObject>(to target: Target,with callback: @escaping (Target, Input) -> Output) {// 赋值callback, 并且weak传入的target值 (这里就把原本我们要写的weak做了)self.callback = { [weak target] input inguard let target = target else {return nil}return callback(target, input)}}// 调用callbackpublic func call(_ input: Input) -> Output? {return self.callback?(input)}// 声明闭包private(set) var callback: ((Input) -> Output?)?// 是否已经赋值callback true已赋值, false未赋值public var isDelegateSet: Bool {return callback != nil}public init() { }}// 这个扩展用到了一个 where Output == Void, 很巧妙.
// 这样的话, 传入output是Void类型, 调用闭包时, 就会自动为无返回值.
extension Delegated where Output == Void {// 调用闭包public func call(_ input: Input) {self.callback?(input)}
}// 这个扩展不需要看太多, 我大致标明一下函数含义就行
extension Delegated {// 赋值闭包, 需要自己写weakpublic mutating func stronglyDelegate<Target : AnyObject>(to target: Target,with callback: @escaping (Target, Input) -> Output) {}// 赋值闭包, 需要自己写weakpublic mutating func manuallyDelegate(with callback: @escaping (Input) -> Output) {}// 删除当前已赋值的闭包public mutating func removeDelegate() {}
}
虽然代码量少, 但是这个思路真的不错, 胜在实用性.
不过这个第三方还有几个点没解决
- 没提供能动态多个weakTarget
- input只有一个参数.
不过这都是小事,明白原理之后, weakTarget可以自己照着写, 多写几个就行.(应该也不会用很多个吧 ✧(≖ ◡ ≖) )
而参数问题, 我们可以不写多几个函数, 我们可以直接用元组, 如下:
// typealias 一个元组类型typealias Login = (acc: String, pwd: String)// Delegated 声明并初始化var callback = Delegated<Login, Void>.init()// 点击登录按钮@IBAction func respondsToBtn(_ sender: Any) {// Delegated 调用闭包self.callback.call(("账号", "密码"))}// 外部赋值闭包self.tView.callback.delegate(to: self) { (self, info) inprint("acc:", info.acc, "\npwd:", info.pwd)}
这样一个参数也无所谓了
示例Demo
写了一个使用示例demo, 两个页面的跳转, 按钮的点击是一个view传到viewController.
展示了普通闭包和使用Delegated的区别
使用普通闭包回跳.
真的容易忘写 /(ㄒoㄒ)/~~ ,自从写Swift以来, 不知道忘写多少次了.
使用Delegated回跳
示例Demo地址
DelegatedDemo
解决Swift中callback循环引用 - Delegated(Library)相关推荐
- 【FastJSON】解决FastJson中“$ref 循环引用”的问题
0.开发环境 SSH,EasyUI,MySQL 1.需求要求: (1)首先获取所有的贷款订单数据,即List <LoanOrder>. (2)然后从单个贷款订单实体LoanOrder去访问 ...
- 解决FastJson中“$ref 循环引用检测”的问题的几种方式
一.现象: 项目中用json形式来存储一个集合对象,用fastjson发现多了一些东西:$ref,了解之后才发现是重复引用的问题. [{"id":"1",&qu ...
- Swift之常见闭包与defer关键字的使用分析和闭包中的循环引用 | CSDN创作打卡
一.什么是闭包? 在 Swift 中,可以通过 func 定义一个函数,也可以通过闭包表达式定义一个函数,闭包是一个捕获了上下文的常量或者是变量的函数.闭包(Closures)是自包含的功能代码块,可 ...
- Javascript 深度克隆中的循环引用问题解决和代码优化
概要 在前端项目开发中,我们经常需要深度克隆JS对象.在克隆代码开发过程中,我们经常会遇到数组判定或对象循环引用的问题. 本文通过实例来解决上述问题 代码及实现 常见深度克隆JS对象的代码 funct ...
- 小记 TypeScript 中的循环引用问题
随着项目规模的不断增长,循环引用问题似乎总是不可避免,本文就 TypeScript 中可能出现的循环引用问题做了一些简单记录~ 平时编写 TypeScript 代码时,一般都倾向于使用模块(Modul ...
- 深入理解C++中的循环引用问题及解决方法
循环引用问题在C++中是指当两个或多个对象互相持有对方的引用(通常是通过智能指针),导致它们的引用计数永远不会降为零,从而导致内存泄漏的情况.这种问题在使用shared_ptr时尤为突出,因为shar ...
- nstimer循环引用_ios开发中经典循环引用场景?
1.属性传值循环引用 如:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexP ...
- 聊一聊 JS 中的循环引用及问题
本文主要从 JS 中为什么会出现循环引用,垃圾回收策略中引用计数为什么有很大的问题,以及循环引用时的对象在使用 JSON.stringify 时为什么会报错,怎样解决这个问题简单谈谈自己的一些理解. ...
- 解决Swift中present(uiImagePickerController,animated: true,completion: nil)闪退的问题
swift中开发选择图片上传,会使用到Tap Gesture Recognizer控件,对应 UITapGestureRecognizer API,以下是代码示例(取自IOS developer li ...
最新文章
- 【图论】【二叉树】以先序字符串方式建立二叉树
- oracle status
- 科学家用大脑控制平板电脑操作 真的可以!
- Part5核心初始化_lesson3---关闭看门狗
- P6砖家:对不起,我没.NET5高并发经验,我要跑路了!
- spring boot入门(九) springboot的过滤器filter。最完整、简单易懂、详细的spring boot教程。
- 关于linux拨号上网的软件实现方案[原创]
- 软件工程 选课系统的uml类图_想成为高级程序猿,面向对象建模和UML你不应该知道?...
- xutil3网络框架
- meshlab模型简化
- Linux 之六 Shell、终端(Terminal)、控制台(Console)、CLI 命令行界面、GUI 图形用户界面(X、X11、Xfree86、Xorg、GNOME、KDE)
- 【3dmax千千问】初学3dmax插件神器第17课|VRAY渲染教程|哪三种表现方式最能影响3dmax疯狂模渲大师设计效果图的写实程度?食住玩3dmax入门到精通进阶教程
- RTL8152网卡灯配置详细说明
- python进行邮件文件.eml.pst.msg信息提取(包括附件)
- 微信小程序:map组件的简单使用,标注callout与label简单用法
- Dharma勒索病毒变种 ---加密后文件后缀.bkpx
- 原生Android打造一个炫酷的底部导航栏
- 量子计算机有生之年,对话哈佛大学教授Lukin:量子计算将在我们有生之年普及!...
- 纯干货!信贷行业电话销售员一定要掌握的电话沟通话术
- 红烧茄条————————炒茄子不费油却很好吃的办法
热门文章
- 家用宽带如何接入所有的房间,只需要电脑和一段网线自己就可以完成
- python爬虫论坛1688_Python爬虫抓取论坛关键字过程解析
- java初级ppt笔记
- php获取空间头像图片的方法
- 微信机器人红包java_安卓微信HOOK,自动好友,自动聊天,自动抢红包,机器人
- Python爬虫爬取新浪新闻内容
- 【微信小程序】【智能春联】春节 “迎春对联” 微信小程序 丨 2022
- php x4co 16进制,北语18春《PHP》作业1234参考
- jQuery——插件
- 6个月的测试经验,来面试居然开口要17K,面试完,我5K都不想给他.....