虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > Swift编程 > swift中利用runtime交换方法的实现示例

swift中利用runtime交换方法的实现示例
类别:Swift编程   作者:码皇   来源:互联网   点击:

这篇文章主要给大家介绍了关于swift中利用runtime交换方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。

前言

Runtime介绍

学习一个东西至少要先知道它是个啥,你一定听说过“运行时是 Objective-C 的一个特色”,这里的“运行时”就是指 runtime 了。

老的方式initialize现在已经不适用了,需要用新的方式代替。

思路: 定义一个启动的协议,在app完成启动的方法里把需要做method swizzle的类跑一边协议的方法

第一种

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

遵循协议SelfAware,实现awake()

第二种(类似第一种)

1、创建一个swizzle注入的协议

    public protocol SwizzlingInjection: class {
    static func inject()}

2、创建swizzle helper

    open class SwizzlingManager {
    //只会调用一次的方法 private static let doOnce: Any? = {
    UIViewController.inject() return nil }
    () open static func enableInjection() {
    _ = SwizzlingManager.doOnce }
    }

3、给UIApplication 创建分类调用那个一次方法

    extension UIApplication{
    open override var next: UIResponder?{
    SwizzlingManager.enableInjection() return super.next }
    }

4、在你需要的类中遵循注入协议

    extension UIViewController: SwizzlingInjection{
    public static func inject() {
    //确保不是子类 guard self === UIViewController.self else {
    return }
    DispatchQueue.once(token: "com.moglo.urmoji.UIViewController") {
    //do swizzle method }
    }
    }

once只执行一次的方法

    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) }
    }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关热词搜索: swift runtime交换 swift runtime swift4