作者:字节移动技能——段文斌
前言
众所周知,准确的举荐离不开许多埋点,常见的埋点搜集计划是在呼应用户行为操作的途径上进行埋点。可是由于App一般会有比较多界面和操作途径,自动埋点的保护本钱就会非常大。所以作业的做法是无埋点,前端和后端的差异而无埋点结束需求AOP编程。appear
一个常见的场景,比如想在UIViewController
出application现和消失的时刻分别记载时刻戳用于计算页面展示的时长。要抵达这javascript是干什么的个政策有许多种办法,可是AO前端开发是干什么的P无疑是最简略有用的办法。Objective-C的Hook其实也有许多种办法,这儿以Method Swizzle给个示例。
@interface UIViewControl前端开发是干什么的ler (MyHook)
@end
@implementation UIViewController (MyHook)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceTokeapproachn, ^{
/// 惯例的 Method Swizzl前端面试题e封装
swizzleMeth产品战略odjavascript什么意思s(self, @selector(viewDidAppear:), @selector(my_viewDidAppappointmentear:));
/// 更多Hook
});
}
- (void)my_viewDidAppear:(BOOL)animated {
/// 一些Hook需求的逻辑
/// 这儿调用Hook后javascript菜鸟教程的办法,产品设计其结束其结束已是原办法了。
[self my_viewDidAppear: anapproachimated];
}
@end
接下来我APP们讨论一个详细场景:
UICollectionView
或许UITableView
是iOS中非常常用的列表UI组件,其间列表元appstore素的点击事情回调是经过delegate
结束的。这儿以UIColle前端学什么ctionVapproveiew
为例,UICollectionView
的delegate
,有个办法声明,collectionViappstoreew:didSelectItemAtIndexPath:
,结束这个办法咱们就能够给application列表元素添加点击事情。
咱们的政策是Hook这个delegate的办法,在点击回调的时分进行额javascript:void(0)定的埋点操作。
方apple案迭代
计划1 Method Swizzle
一般状况下,Method Swizzle能够满意绝大部分的AOP编程需求。因此首次迭代,咱们直接运用Method Swizzle来进行Hook。
@interface UICollectionView (MyHook)
@end
@implementation UICollectionView (MyHook)
// Hook, setMyDelegjavascript:void(0)ate:和setDelegate:交流过
- (void)s产品批号是生产日期吗etMyDelegate:(id)delegate {
if (delegateapple != nil) {
/// 惯例Method Swizzle
swizzleMappreciateethodsXXX(delegajavascript菜鸟教程te, @selector(collectionView:didSelectItemAtIndexPath:), self, @selector(my_collectionView:didSelectItem产品运营AtIndexPath:));
}
[self setMyDelegate:nil];
}
- (v产品oid)my_collectionView:(UICollectionView *)ccollectionView didSelectItemAtIndexPath:(NSIndexPajavascript数据类型th *)index {
//前端开发是干什么的/ 一些Hook需求的逻辑
/// 这儿调用Hook后的办法,其结束其结束已是原办法了。
[self my_collectionView:ccollectionView didSelectItemAtjavascript:void(0)IndexPath:index];
}
@end
咱们把这个计划集成到今天头条App里边进行查验验证,发现无法办法验证经过。
主要原因今天头条App是一个庞大的项目,其间引入了非常多的产品设计三方库,比如IGListKit等,这些三方库前端工程师一般对UICollectionView
的运appstore用都进行了封装,而这招聘海报些封装,恰恰导致咱们不能运用惯例的Method Swizzle来Hook这个delegate。直接的原因总结有以下两点:
-
setDelega产品司理te
传入的政策不是结束UICollectionViewD前端开发需求把握什么技能elegappearanceate
协议的那个政策
如图示,setDelegate
传入的是一个署理政策proxy,proxy引证了实践的结束UICollectionViewDelegate
协议的delegate
,appleproxy实践上并没有结束UICollectionViewDelegate
的任前端和后端的差异何一个办法,它把一切办法都转发给实践的delegate
。这种状况下,咱们不能直接对proxy进行Method Swizzle
- 屡次
setDelegate
在上述图例中,运用方存在连续调用两次setDelegate
的状况,第一次是实在delegate
,第2次是proxy
,咱们需求差异对待。
署理办法和NSProxy介绍
运用proxy对原政策进行javascript署理,在处理完额外操作之后再调用原政策,这种appearance办法称为署理办法。而Objective-C中要结束署理办法,运用NSProxy会招聘比较高效。详细内容参看下列文章。
- 署理办法
- NSProxy运用
这儿面UICollectionView
的setDelegate
传入的是一个proxy
对错javascript:void(0)常常见的javascript九九乘法表操作,比如IGListKit,一起Ajavascript是干什么的pp根据自身需求,也有或许会做这一层封装。
在UICollectionView
的setDelegate
的时分,把delegate
包裹在proxappley
中,然后把proxyapprove设置给UICollect前端训练组织ionView
,运用proxy
对delegate
进行音讯转发。
计划2 运用署理办法
计划1现已无法满javascript什么意思意咱们的需求了,咱们前端考虑到既javascript:void(0)然对delegate
进行署理是一种惯例招聘操作,咱们何不也运用署理办法approach,对proxy
再次署理。
代码结束
- 先Hook
UICollectionView
的sejavascript:void(0)tDelegate
办法 - 署前端理
delegate
简略的代码暗前端开发需求学什么示如下
/// 完好封装了一些惯例的音讯转发办法
@interface DelegaAPPteProxy :appointment NSProxy
@property (nonatomic, weak, readonly) id t招聘图片大全图片美观arget;前端学什么
@end
/// 为 CollectionViappleew delegate转发音讯的proxy
@interface BDCollectionViewDelegJavaScriptateProxy : DelegateProxy
@end
@implementation BDCollectionViewDelegateProxy <UICollectionViewDelegate>
- (void)collectionVjavascript九九乘法表iew:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
//t前端rack eAPPvent here
if ([self.target respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) {
[self.target collectionView:cojavascript面试题llectionView didSelectItemAtIndexPath:indexPath];
}
}
- (BOOL)bd_ijavascript九九乘法表sCollectionViewjavascript菜鸟教程TrackerDecorator {
return YES;招聘
}
// 还有其他的音讯转发的代码 先忽略
- (BOOL)respondsToSejavascript高档程序设计lector:(SEL)aSelector {
if (aSelector == @selector(bd_isCollectionViewTrackerDecorator)) {
return YES;
}
return [self.target respondsToSelector:aSelector];
}
@end
@interface UICollec招聘启事tionView (MyHook)
@end
@implementatjavascript菜鸟教程i招聘信息最新招聘2021on UICollect前端工程师ionView (MyHook)
- (void) setDd_TrackerProxy:(BDCollectionViewDelegateProxy *)object {
objc_app装置下载setAssocjavascript九九乘法表iatedObject(se招聘图片大全图片美观lf, @selector(bd_TrackerProxy), object, OBJC_ASSOCIATION_RETAINappstore_NONATOMIC);
}
- (BDCollectionVieJavaScriptwDelegateProappreciatexy *) bd_TrackerProxy {
BDCollectionViewDelegateProxy *bridgapprovee = objc_getAssociatedObject(self, @selector(bd_TrackerProxy));
return bridge;
}
// Hook, setMyDelegate:和setDelegate:交流过了
- (void)setMyDelegate:(id)delegate {
if (delegate == nil) {
[s前端和后端哪个薪酬高elf setMyDelegate:delegate];
return
}
// 不会开释,不重复设置
if ([delegate respondsToSelector:@产品定位selector(bd_isCollectionViewTrackerDeco产品运营rator)]) {
[self setMyDelegate:delegate];
return;
}
BDCollectionViewDelegateProxy *proxy = [[BDCollectionViejavascript:void(0)wDelegateProxy alloc] initWithTarget:delegate];
[self setMyDelegate:proxy];
self.bd_TrackerProxy = proxy;
}
@end
模型
下图实线标明强引证,虚线标明弱引证。
状况一
假定运用方没有对delegate
进行署理,而咱们运用署理办法
-
UICollectionView
,其delegat前端训练组织e
指针指向DelegateProxy - DelegatePro产品生命周期xy,被UICollejavascript九九乘法表ctionVi前端开发需求把握什么技能ew用runtime的办法强引证,其target弱引证实在Delegate
状况二
假定运产品设计用方也对delegate
进行署理,咱们运用署理办法javascript数据类型
- 咱们只需求保证咱们的De产品运营legat前端工程师eProxy处于署理链中的一环即可
从这儿咱们能够看出,署理app装置下载办法有很好的扩展性,它容许署理链不断嵌套,只需咱们都遵循署理办法的准则即可。
到这儿,咱们的appear计划现已在今天头条App上查验经过了。可是作业远还没有结束。
踩坑之旅
现在的还算比较能够,可是也不能完全防止问题。这儿其实不仅仅是Ujavascript什么意思ICollectionView的de招聘信息最新招聘2021legate,包括:
- U前端开发需求学什么IWebView
- WKWebView
- UITab招聘启事leView
- UICollectionViejavascript高档程序设计w
- UIScrollView
- UIActionSheet
- UIAlertView
咱们都选招聘海报用相同的办法来进行Hook。一起咱们将计划封装一个SDK对外供给,以下统称为产品运营MySDK。
第一次踩坑
某客户接入咱们的方招聘案之后,在集成过程中反应招聘模板有必现Crash,下面详细介绍一下这一次踩坑的经历。
库房信息
要害信招聘息是[UIWebView webVi产品战略ew:decidePolicyForNavigationActi前端开发需求学什么on:request:frame:decisionListener:]
。
Thread 0 Crashed:
0 libobjc.A.dylib 0x00000001819844产品设计专业3c objc_msgSend + 2appear8
1 UIKit 0x000000018be05b4c -[UIWebView wejavascriptbView:decidePolicyForNavigationAction:request:frame:decisionListener:招聘模板] + 200
2 Core招聘求职Foundation 0x0000000182731cd0 __invoking___ + 144
3 CoreFoundation 0x000000018261056c -[NSInvocation invoke] + 292
4 CoreFoundation 0x00000001产品设计专业8261501c -[NSInvocation invokeWithTarget:] + 60
5 WebKitLegacy 0x000000018b86d654 -[_WebSafeForwarder forwardInvocation:] + 156
从库房信息不难判别出crash原因是UIWebV前端面试题iew的delegate野指针,那为啥出现野指针呢?
这儿先说明一下crash的直接原因,然后再来详细分析为什么就出javascript数据类型现了问题。
- MySDK对setDelegate进行了Hook
- 客户也对setDelegate进行了Hook
- 先application实施MySDK的Hook逻辑调用,然后实施客户的Hook逻辑调用
客户Hook的代码
@interface UIWebView (JSBridge)
@end
@ijavascript九九乘法表mplementation UIWeapp装置下载bView (JSBridge)产品生命周期
- (voijavascript:void(0)d)setJsBridge:(产品运营id)object {
objc_setAssociatedObject(self, @selector(jsBridge), object, OBJC_ASSOCI前端训练组织ATION_RETAIN_NONATOMIC);
}
- (WebViewJavascriptBridge *)jsBridge {
WebV招聘网站哪个靠谱iewJavascriptBridge *bridge = objc_getAssociatedObject(self, @selectorapp装置下载(jsBridge));
return bridge;
}
+ (void)load {
static dispatch_once_t onceToken;
dapproveispatch_once(&onceToken, ^{
swizzleMethods(self, @selector(setDelegate:), @selector(setJSBridgeDelegate:招聘案牍));
swizzleMethods(self, @selector(initWithFrame:), @selector(initJS招聘求职WithFrame:));
});
}
- (instancetypjavascripte)initJSWithFrame:javascript高档程序设计(CGRect)frame {
self = [self initJSWithFrame:frame];
if (seljavascriptf) {
WebViewJavascriptBridge *bridge产品战略 = [WebViewJavas招聘海报criptBridge bridgeForWebView:self];
[self setJs前端面试题Bridge:bridge];
}
return self;
}
/// webview.delegate = xxx 会被调用屡次且传入的政策不一样
- (void)setJSBridgeDelegate:(id)delegate {
WebViewJavascriptBridge *bridge = self.jsBridge;
if (delegate == nil || bridge == nil) {
[self setJSBridgeDelegate:dele前端gate];
} else if (bridge == delegate) {
[self setJSBridgeDelegatejavascript什么意思:delegate];
} else {
/// 第一次进入这儿传入 bridge
/// 第2次进入这儿传入一个delegate
if (![delegate isK前端和后端的差异indOfClass:[WebViewJavascriptBridge class]产品战略]) {
[bridge setWebViewDelegate:delegate];
/// 下招聘面这一行代码是客户缺少的
/// fix with this
[self setJSBridgeDelegate:bridge]产品生命周期;
} else {
[self setJSBridgeDelegate:del产品介绍egate];
}
}
}
@end
MySDK Hook代码
@inter招聘模板face UIWebappstoreVi招聘案牍ew (MyHook)
@end
@implementa前端和后端哪个薪酬高tion UIWebView (MyHook)
// Hook, setWebViewDelegat招聘网站哪个靠谱e:和setDelegate:交流过
- (void)setWebViewDelegate:appreciate(id)delega招聘模板te {
if (delegate == nil) {
[self setWebViewDelegate:delegate];
}
BDWebViewDelegateProxy *p产品设计roxy = [[BDWebViewDelegateProxy alloc] initWithTarget:delegate];
self.bd_appointmentTrackerDecorator = proxy;
[self setWebViewDelegate:proxy];
}
@end
野指针原因
UIWebView有两次调用setDelegate办法,第一次是传的WebViewJavascriptBridge,第2次传的另一个实践的WebViewDelegate。暂时称第一次传了bridge第2次传了实践上的delegate。
- 第一次调用,MySDK Hook的时分会招聘模板用DelegateProxy包装住bridge,一切办法经过DelegateProxy转发到brid前端开发需求把握什么技能ge,这儿传给
setJSBridgeDelegate:(id)del前端和后端的差异egate
的delegate实践上是DelegateProxy而非b招聘求职ridge。
这儿需求留心,UIWebView的delegate指向DelegateProxy是客户给设置上的,且这个特点assign而非weak,这个assign很要害,assigin在政策开招聘求职释之后不会自动变为nil。
- 第2次调用,MySDK Hook的时分会用新的DelegateProxy包装住delegate也就是WebViewDelegate,这个时分MySDK的逻辑是把新的DelegateProxy给强引证中,老的DelegateProxy就失去了强引证因此开释了。
此时的状况假定不做任何处理,当时状况就如图示:
- delegate指向现已开释的DelegateProxy,野指针
- UIWebviewapp装置下载触发回调就导致crash
批改办法
假定补上那一句,招聘网站哪个靠谱setJSBridgejavascript:void(0)Delegate:(id)delegate
在判别了delegate不是bridge之后,把UIWebView的delegate设置为bridge就能够结束了。
注释中 fix wit前端h this下一行代码
批改后模型如下图
总结
运用Proxy的办法虽然也能够处理必定的javascript九九乘法表问题,可是也需求运javascript用方遵循必定的规范,要意识到第三方S产品DK也或许setDelegate
进行Hook,也或许运用Proxy
第2次踩坑
先补偿一些参看资料
- RxCocoa前端源码参看 github.com/ReactiveX/R…
- rxcocoa学习-DelegateProxy
RxCocoa也运用appreciate了署理办法,对delegate进行了署理,按道理应该没appstore有问题。可是RxCappearanceojavascript面试题coa的结束有点出入。
RxCocoa
假定独自只运用了RxCocoa的计划,和计划是一起,前端和后端的差异也就不会有任何问题。
RxCocoa+MySDK
RxCocoa+MySDK之后,变成这样子。UICollectionView的delegate直接指向谁在于谁调用的setDelegate
办法后调。
理论也应该没有问题,产品战略就是引证链多一个poxy包装算了。可是招聘案牍实践上有两个问题。
问题1
R前端面试题xCocoa的delegate的get办法射中asserapplet
// UIScrollView+Rx.swift
extension Reactive where Base: UIScrollView {
public var d前端开发需求把握什么技能elegate: DelegateProxy前端开发需求把握什么技能<UIScrollView, UIScrollViewDelegate> {
return RxScrollVie招聘启事wDelegateProxy.proxy(for: base)
// base能够理解为一个UIScrollView 实例
}
}
open class RxS产品设计专业crollViewDelegateProxy {
public static func proxy(for objavascript是干什么的ject:前端训练组织 ParentObject) -> Self {
let maybeProxy = self.assignedProxy(for: obje招聘图片大全图片美观ct)
let proxy: AnyObjeappreciatect
if let existingProxy = maybeProxy {
proxy = existingProxy
} else {
proxy = castOrFatalError(self.createProxy(for: obj前端学什么ect))
sel产品运营f.assignProxy(proxy, toObject: object)
assert(self.assignedProxy(for: object) === proxy)
}
let currentDelegate = self._currentDelegate(for: object)
let delegateProxy: Self = castOrFatalError(proxy)
if currentDelegate !== delegateProxy {
delegateProxy._setForwardToDe产品生命周期legate(currentDelegaappearancete, retainDelegate: false)
assAPPert(delegateProxy._forwardToDelegate() === cur产品设计专业rentDelegate)
self._setCurrentDelegate(proxy, t产品批号是生产日期吗o: object)
/// 射中下面这一行assert
assert(self._cu前端开发rrentDelegate(for: object) === proxy)
assert(dejavascript是干什么的legateProxy._forwardToDelegate() === currentDelegate)
}
return delegateProx产品战略y
}
}
要害产品介绍逻辑
- delegateProxy即便Rxjavascript权威攻略DelegateProxy
- currentDelegaJavaScriptte为RxDelegateProxy指向的政策
- RxDele前端gateProxy._setForwardToDelegate把RxDelegatePro招聘海报xy指向实在的Delegate
- 标红的前面一句实施的时分,是调用setDele产品批号是生产日期吗gate办法,把RxDelegateProxy的proxy设置给UIScrollView(其实是一个UICollectionView实例)
- 然后进入了MySDK的Hook办法,把RxDelegateProxy给包了一层
- 究竟结果如下图
- 然后导致self._currentDelegate(for: object) 是De前端和后端的差异legateProxy而非RxDelegateProxy,触发标红断语
这个断语就很霸道javascript面试题,相当于RxCocoa认为就只需它能够去运用Proxy包装d产品运营elegate,其他人不能这样做,只需做了,就断语。
进一招聘求职步分析
- 当时状况
- 再次进入Rx的办法
- currentDelegate是UICollectionView指向的DelegateProxy(MySDK的包装)
- delegateProxy指向仍是RxDelegateProxy
- 触发Rx招聘海报的if判别,Rx会把其指向实在的delegate改向UICollectionView指向的DelegateProxy
- 导致循环指向,引证链中实在的Delegate丢掉了
问题2
上面说到屡次调用导致前端了循环指向,而循环指向导致了在实践的办法转发的时前端开发需求把握什么技能分变成了死循环。
responds代码
open招聘案牍 class RxScrollViewDelegateProxy {
override open func responds(to aSelector: Selector!) -> Bo招聘软件ol {
return super.responds(to: aSelector)
|| (self._forwardToDelegate?.responds(to: aSelector) ?? false)
|| (self.voidDelegateMethodsContain(aSelector) && self.hasObservers(selecto产品设计r: aSelector))
}
}
@implementation BDColle产品战略ctio招聘nViewDelegateProxy
- (BOOL)respondsToSelector:(SEL)javascriptaSelector {
if (aSelector == @selector(bd_isCollectionViewTrackerDecorator)) {
return YES;
}
return [super respondsToSelappearector:aSelector];
}
@end
如同只需不屡次调用就没有问题了?
要害在于Rx的setDelegate办法也调用了前端学什么get办法,导致一次get就触发第2招聘信息最新招聘2021次调用。也就是屡次调用是无法防止。
处理计划
问题的原因比较显着,假定改造RxCocoa的代javascript什么意思码,把第三方或许的Hook考虑进来,前端完全招聘启事能够处理问题。
处理计划1
参看MySDK的pappearancerox前端开发需求学什么y计划,在javascriptproxy中参加一个特别办法,来判别RxDelegateProxy是否现已在引证链中,而不去自动改动产品战略这个招聘求职引证链。
open cljavascriptass RxScrollViewDelegateProxy {
public static func proxy(for object: ParentObject) -> Self {
...
let currentDelegate = self._curapproverentDelegate(for: object)
let delegateProxy: Selapprovef = castOrFatalError(proxy)
//if currentDelegate !== delegateProxy
if !currentDapproachelegate.resp产品质量法onds(to: xxxMethod) {
delegateProxy._setForwardToDelegate(currentDelegate, retainDelegate: false)
assert(delegateProxy._forwardToDelegate() === currentDelegate)
self._setCjavascript高档程序设计urrentDelegate(proxy, to: object)
assert(self._currentDelegajavascript面试题te(for: object) === proxy)
assert产品定位(dejavascriptlegateProxy._forwardToDelegate()前端开发 === currentDelegate)
} else {
return curren招聘求职tDelegate
}
return招聘 delegateProxy
}
}
相似这样的改招聘网站哪个靠谱造,就appearance能够处理问题。咱们与Rx团队进行了交流,也提了PR,迷惘究竟被拒绝合入了。Rx给出的说明是,Hook是不典雅的办法,不举荐Hook体前端开发是干什么的系的任何办法,也不想兼容任何第三方的Hook。
处理计划2
有没有或许,RxCocoa不改代码,MySDK来兼容?
刚才说到,有或许是两种状况。
- 状况1
- setDeleappearancegate的时分,先进Rx的办法,后进MySDK的Hook办法,
- 传给Rx的就是delegat前端开发e
- 传给MySDK的是RxDelegateProxy
- Delegate的get调用就触发bug
- 状况2
- setDelegate的时分,javascript权威攻略先进MySDK的Hook办法,后进Rx的办法?
- 传给Rx的就是DelegateProxy
其实假定是状况2,如同Rxcocoa的bug是不会招聘图片大全图片美观复现的。
可是细心查看Rxcocoa的setDelegate代码
extension Reactive where Base: UIScrollView {
public func setDelegate(_ delegate: UIScrollViewDelegate)
-> Disposable {
return RxSjavascript是干什么的crollViewDelegateProxy.installForwardDelegate(delegate, retainDelegate: false, onProxyForO前端工程师bject: self.base)
}
}
open class RxScrollViewDelegateProxy {
public static func installForwardDelegate(_ forwardDelegaapplicationte: Delegate, retainDelegate: Bool, onappstoreProxyForObject object: ParentObject) -> Disposable {
weak var weakFoAPPrwardDelegate: AnyObject? = forwardDelegate as AnyObject
let proxy = self.proxy(for: object)
assert(proxy._javascript九九乘法表forwardToDelegate() === nil, "")
proxy.setForwardToDelegate(forwardDelegate, rappearetainDelegaappreciatete: retainDelegate)
return Disposables.create {
...
}
}
}
emmm?Rx里边,UICo前端开发llecjavascript九九乘法表ti招聘网站哪个靠谱onView的setDelegate和Delegate的get办法不是Hook…
collectionView.rx.setDelegate(delegate)
let delegate = collectionView.rx.delegate
究竟流程就只能是
- setDelegatejavascript的时分,先进Rx的办法,传给Rx实在的del前端开发需求把握什么技能egate
- 后进MyS产品战略DK的Hook办法
- 传给M前端开发是干什么的ySDK的是RxDe招聘求职legateProxy
- Rx里边获取CollectionView的delegate触发判别
- Delegaapprovete的get调用就触发bug
假定Myjavascript九九乘法表SDK仍是选用当时的Hook计划,就无法在javascript面试题MySDK处理了。
处理javascript是干什么的计划3
细心看了一下,approach发现Rx里边是经过重写RxDelegateProxy的forwardInvocation来抵达办法转发的目的,即application
- RxDelegateProxy没有结束
UICollectionViewDelegate
的任何办法 - forwardInvocation中处理
UICollectionViewDelegate
相关回调
回顾音讯转发招聘启事机制
咱们能够产品战略在forwardingTargetForSelector这一步进行处理,这样能够避开与Rx相关的冲突,处理完再直接产品介绍越过。
- forwardingTargetForSelector中针对delegate的回调,target返回一个SDK处理的类,比DeleappointmentgateJavaScriptProxy
- DeljavascriptegateProxy上报结束之后,直接调用跳到RxDelegateProJavaScriptxy的forwardInvocation办法
这个处理计划其实也不完美,只能暂时逃避与Rx的冲突。假定后续有其他SDK也来在这个阶段招聘网站哪个靠谱处理javascript高档程序设计Hook冲突,也简单出现问题。
总结
的确如Rx团队描绘的那样,Hook不是很典雅的办法,任何Hook都有或许存在兼容性问题。
- 谨慎运用Hook
- Hook系统接口必定要遵循必定的规范,不能想象只需你在Hook这个接口
- 不要想象其他人javascript面试题会怎样处理,直接把多种计划集成到一起,构建多种场景,查验兼容性
文章列举的计划或许不全或许不完善,假定有更好的计划,欢迎讨论。
参看文档
- NSProxy运用
- 署理办法
- rxcocoa学习-DelegateProxy
- github.com/ReactiveX/R…
关于字节移动途径团队
字节跳application动移动途径团队(Client Infrastructure)是大前端根底技招聘术作业领军者,担任整个字节跳动的我国区大前端根底设施制作,提高公司全产品线的功用、稳定性和工程功率,支撑的javascript是干什么的产品包括但不限于抖音、今天头条、西瓜产品介绍视频、火山小视频等,在移动端、Web、Desktop等各终端都有深入研究。
就是现在!客户端/前端/服务端/端智能算法/查验开发 面向全球规划招聘!一起来用技能改动世界,感兴趣能够联系邮箱 chenxuwei.cxw@bytedance.c前端开发om,邮件主题 简历-姓名-求职意向-期望城市-电话。