废话开篇:对于 iOS 下的代理,一般都会想到 delegate,比如最常用的 UITableView 的delegate,这里代理的作用就方便开发者去调用自身类以外的某些方法,来实现某些的业务场景下的通信。在 OC “消息转发”的大环境下,NSProxy 代理类为开发者提供了更多的角度思路来处理代码逻辑。JS 下的 Proxy 也是代理,Vue2.0 实现双向绑定用的还是 defineProperty 属性的声明来重写 set get 方法,Vue3.0 便利用了 Proxy 代理 set get 方法来双向绑定。下面就看看这 OC 下的 NSProxy 与 JS 下的 Proxy 的简单的应用场景。
场景一、 OC 下的 NSProxy
OC 下的 NSProxy 利用的是消息转发机制,大致的的意思就是:OC 语言会给一个对象调用的本类找不到方法提供一些额外的判断,比如:是否去执行本类的其他方法,是否可以让其他实例对象执行当前找不到的方法...最后,仍然没有处理这条消息,那么,崩溃。
这里创建 WSLProxy 代理类
这里创建 Person 类
让代理执行一个方法,通过消息转发发送给代理对应下的 target 去执行。
这时候,代理的就会把 lookAtMine: 方法进行转发,最后在代理类的 forwardInvocation 方法里处理消息。
这里有个注意的地方,当 WSLProxy 的target 用 weak 修饰的时候,在消息转发的时候很可能会释放掉,所以,没有指定对象去处理方法签名后,当前的代理类的消息转发就此结束,崩溃了,因此,这里需要用 strong 修饰,注意的是:定时器下的 target 必须要用 weak 修饰,防止强引用链穿到类似 UIViewController 等作为真正执行定时器任务的对象。
定时器的释放问题的处理,此时的 WSLProxy 的target 必须用 weak 修饰
在 UIViewController 的 dealloc 里面进行定时器的释放。
在执行 pop 方法后,控制器销毁了
场景二、 JS 下的 Proxy
这里简单的实现一下基于 uniapp 的网络请求的切面写法,一般 uniapp 的网络请求是通过 uni.request 方法实现的,那么,就 代理一下这个 request 方法,拓展中间件,实现统一加载提示框。
//导出模块
export default new Proxy({}, {
get(target, name) {
//返回方法,方法参数是网络请求参数,方法的返回值是异步对象
return (obj) => new Promise((resolve, reject) => {
obj.url = 'baseuUrl' + obj.url;
obj.header = Object.assign({
"Content-Type": 'application/json',
}, obj.header);
//请求前展示加载视图
uni.showLoading({
title: '加载中',
mask: true
})
//这里等同于 uni.request() 方法调用
uni[name]({
...obj,//网络请求参数
success: ret => {
//网络请求完成
if (ret.statusCode == 200 || ret.data.code === 200) {
//成功回调
resolve(ret.data)
} else {
//提示错误信息
uni.showToast({
title: ret.data.message,
icon: 'none'
})
//报错警告
reject(ret.data)
}
},
fail: err => {
//报错警告
reject(err)
},
complete: () => {
//隐藏加载视图
uni.hideLoading()
}
})
}).catch((e) => {
//catch
console.log(e)
})
}
})
方法的调用,这里直接用对象调用了 request 方法,在代理的 get 方法里直接进行了 uni 的 request 方法。
HTTP.request({
'url':'12',
}).then(result=>{
})
好了,上面是极其简单的 OC 下的 NSProxy 与 JS 下的 Proxy 简单应用场景,面对复杂的开发业务逻辑,还是要选择合适的开发模式。
思路笔记,大神勿笑。