swift中利用runtime交换方法的实现示例
前言
Runtime介绍
学习一个东西至少要先知道它是个啥,你一定听说过“运行时是Objective-C的一个特色”,这里的“运行时”就是指runtime了。
老的方式initialize现在已经不适用了,需要用新的方式代替。
思路:定义一个启动的协议,在app完成启动的方法里把需要做methodswizzle的类跑一边协议的方法
第一种
1、StepOne
protocolSelfAware:class{
staticfuncawake()
}
classNothingToSeeHere{
staticfuncharmlessFunction(){
lettypeCount=Int(objc_getClassList(nil,0))
lettypes=UnsafeMutablePointer.allocate(capacity:typeCount)
letautoreleasingTypes=AutoreleasingUnsafeMutablePointer(types)
objc_getClassList(autoreleasingTypes,Int32(typeCount))
forindexin0..
2、steptwo
extensionUIApplication{
privatestaticletrunOnce:Void={
NothingToSeeHere.harmlessFunction()
}()
overrideopenvarnext:UIResponder?{
//CalledbeforeapplicationDidFinishLaunching
UIApplication.runOnce
returnsuper.next
}
}
3、stepthree
遵循协议SelfAware,实现awake()
第二种(类似第一种)
1、创建一个swizzle注入的协议
publicprotocolSwizzlingInjection:class{
staticfuncinject()
}
2、创建swizzlehelper
openclassSwizzlingManager{
//只会调用一次的方法
privatestaticletdoOnce:Any?={
UIViewController.inject()
returnnil
}()
openstaticfuncenableInjection(){
_=SwizzlingManager.doOnce
}
}
3、给UIApplication创建分类调用那个一次方法
extensionUIApplication{
openoverridevarnext:UIResponder?{
SwizzlingManager.enableInjection()
returnsuper.next
}
}
4、在你需要的类中遵循注入协议
extensionUIViewController:SwizzlingInjection{
publicstaticfuncinject(){
//确保不是子类
guardself===UIViewController.selfelse{return}
DispatchQueue.once(token:"com.moglo.urmoji.UIViewController"){
//doswizzlemethod
}
}
}
once只执行一次的方法
publicextensionDispatchQueue{
privatestaticvar_onceTracker=[String]()
publicclassfunconce(file:String=#file,function:String=#function,line:Int=#line,block:()->Void){
lettoken=file+":"+function+":"+String(line)
once(token:token,block:block)
}
/**
Executesablockofcode,associatedwithauniquetoken,onlyonce.Thecodeisthreadsafeandwill
onlyexecutethecodeonceeveninthepresenceofmultithreadedcalls.
-parametertoken:AuniquereverseDNSstylenamesuchascom.vectorform.oraGUID
-parameterblock:Blocktoexecuteonce
*/
publicclassfunconce(token:String,block:()->Void){
objc_sync_enter(self)
defer{objc_sync_exit(self)}
if_onceTracker.contains(token){
return
}
_onceTracker.append(token)
block()
}
//delay
typealiasTask=(_cancel:Bool)->Void
@discardableResult
staticfuncdelay(time:TimeInterval,task:@escaping()->())->Task?{
funcdispatch_later(block:@escaping()->()){
DispatchQueue.main.asyncAfter(deadline:DispatchTime.now()+time,execute:block)
}
varclosure:(()->())?=task
varresult:Task?
letdelayedClosure:Task={
cancelin
ifletinternalClosure=closure{
ifcancel==false{
DispatchQueue.main.async(execute:internalClosure)
}
}
closure=nil
result=nil
}
result=delayedClosure
dispatch_later{()->()in
ifletdelayedClosure=result{
delayedClosure(false)
}
}
returnresult
}
staticfunccancel(task:Task?){
task?(true)
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。