swift中利用runtime交換方法的實現(xiàn)示例
前言
Runtime介紹
學習一個東西至少要先知道它是個啥,你一定聽說過“運行時是 Objective-C 的一個特色”,這里的“運行時”就是指 runtime 了。
老的方式initialize現(xiàn)在已經(jīng)不適用了,需要用新的方式代替。
思路: 定義一個啟動的協(xié)議,在app完成啟動的方法里把需要做method swizzle的類跑一邊協(xié)議的方法
第一種
1、Step One
protocol SelfAware: class {
static func awake()
}
class NothingToSeeHere {
static func harmlessFunction() {
let typeCount = Int(objc_getClassList(nil, 0))
let types = UnsafeMutablePointer<AnyClass?>.allocate(capacity: typeCount)
let autoreleasingTypes = AutoreleasingUnsafeMutablePointer<AnyClass?>(types)
objc_getClassList(autoreleasingTypes, Int32(typeCount))
for index in 0 ..< typeCount { (types[index] as? SelfAware.Type)?.awake() }
types.deallocate(capacity: typeCount)
}
}
2、step two
extension UIApplication {
private static let runOnce: Void = {
NothingToSeeHere.harmlessFunction()
}()
override open var next: UIResponder? {
// Called before applicationDidFinishLaunching
UIApplication.runOnce
return super.next
}
}
3、step three
遵循協(xié)議SelfAware,實現(xiàn)awake()
第二種(類似第一種)
1、創(chuàng)建一個swizzle注入的協(xié)議
public protocol SwizzlingInjection: class {
static func inject()
}
2、創(chuàng)建swizzle helper
open class SwizzlingManager {
//只會調(diào)用一次的方法
private static let doOnce: Any? = {
UIViewController.inject()
return nil
}()
open static func enableInjection() {
_ = SwizzlingManager.doOnce
}
}
3、給UIApplication 創(chuàng)建分類調(diào)用那個一次方法
extension UIApplication{
open override var next: UIResponder?{
SwizzlingManager.enableInjection()
return super.next
}
}
4、在你需要的類中遵循注入?yún)f(xié)議
extension UIViewController: SwizzlingInjection{
public static func inject() {
//確保不是子類
guard self === UIViewController.self else { return }
DispatchQueue.once(token: "com.moglo.urmoji.UIViewController") {
//do swizzle method
}
}
}
once只執(zhí)行一次的方法
public extension DispatchQueue {
private static var _onceTracker = [String]()
public class func once(file: String = #file, function: String = #function, line: Int = #line, block:()->Void) {
let token = file + ":" + function + ":" + String(line)
once(token: token, block: block)
}
/**
Executes a block of code, associated with a unique token, only once. The code is thread safe and will
only execute the code once even in the presence of multithreaded calls.
- parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
- parameter block: Block to execute once
*/
public class func once(token: String, block:()->Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
//delay
typealias Task = (_ cancel : Bool) -> Void
@discardableResult
static func delay(time : TimeInterval, task: @escaping () -> ()) -> Task? {
func dispatch_later(block : @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time , execute: block)
}
var closure : (() -> ())? = task
var result : Task?
let delayedClosure : Task = {
cancel in
if let internalClosure = closure {
if cancel == false {
DispatchQueue.main.async(execute: internalClosure)
}
}
closure = nil
result = nil
}
result = delayedClosure
dispatch_later { () -> () in
if let delayedClosure = result {
delayedClosure(false)
}
}
return result
}
static func cancel(task : Task?) {
task?(true)
}
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- 簡單好用的iOS導航欄封裝.runtime屬性控制實例代碼
- OC runtime學習筆記之關(guān)聯(lián)對象
- iOS開發(fā)中runtime常用的幾種方法示例總結(jié)
- iOS中Runtime的幾種基本用法記錄
- runtime獲取屬性和成員變量方法
- iOS利用Runtime實現(xiàn)友盟頁面數(shù)據(jù)統(tǒng)計的功能示例
- iOS runtime動態(tài)添加方法示例詳解
- 詳解Java中Checked Exception與Runtime Exception 的區(qū)別
- Java編程使用Runtime和Process類運行外部程序的方法
- 將cantk runtime嵌入到現(xiàn)有的APP中的方法
相關(guān)文章
Swift免費短信驗證碼實現(xiàn)及動態(tài)倒計時功能
這篇文章主要介紹了Swift免費短信驗證碼實現(xiàn)及動態(tài)倒計時功能的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-02-02
Swift自定義iOS中的TabBarController并為其添加動畫
這篇文章主要介紹了Swift自定義iOS中的TabBarController并為其添加動畫的方法,即自定義TabBarController中的的TabBar并為自定義的TabBar增加動畫效果,需要的朋友可以參考下2016-04-04

