DYFSwiftRuntimeProvider 2.1.1

DYFSwiftRuntimeProvider 2.1.1

Tenfay维护。



  • Tenfay

DYFSwiftRuntimeProvider

DYFSwiftRuntimeProvider对Objective-C的运行时进行了封装,并提供了一些常用用法。

License MIT  CocoaPods版本  CocoaPods平台 

中文说明 (中文说明)

组 (ID:614799921)

安装

使用CocoaPods

use_frameworks!
target 'Your target name'

pod 'DYFSwiftRuntimeProvider'
or
pod 'DYFSwiftRuntimeProvider', '~> 2.0.2'

用法

import DYFSwiftRuntimeProvider添加到您的源代码中。

获取类的所有方法名称

1. 获取类的实例所有方法名称

let instMethods = DYFSwiftRuntimeProvider.supplyMethodList(withClass: UITableView.self)
print("========methods: \(instMethods)")

2. 获取类的所有类方法名称

let clsMethods = DYFSwiftRuntimeProvider.supplyClassMethodList(withClass: UIView.self)
print("========clsMethods: \(clsMethods)")

获取类的所有变量名称

let ivars = DYFSwiftRuntimeProvider.supplyIvarList(withClass: UIButton.self)
print("========ivars: \(ivars)")

获取类的所有属性名称

let properties = DYFSwiftRuntimeProvider.supplyPropertyList(withClass: UIButton.self)
print("========properties: \(properties)")

以该类为例。例如:

class People: NSObject {
    var name: String
    
    public override init() {
        self.name = ""
        super.init()
    }
    
    public init(name: String) {
        self.name = name
    }
    
    @objc dynamic func logName(age: Int) {
        print("========" + name + " is \(age) years old.")
    }
    
    @objc dynamic class func decInfo(age: Int, name: String) {
        print("========decInfo: " + "name: " + name + ", age = \(age)")
    }
    
    @objc dynamic class func decInfo2(age: Int, name: String) {
        print("========decInfo2: " + "name: " + name + ", age = \(age)")
    }
    
    @objc dynamic class func decInfo3(age: Int, name: String) {
        print("========decInfo3: " + "name: " + name + ", age = \(age)")
    }
    
    @objc func eat(foods: [String : Any]) {
        print("========eat foods: \(foods)")
    }
    
    @objc dynamic func run(step: Int) {
        print("========1: \(name) runs \(step) step.")
    }
    
    @objc dynamic func run2(step: Int) {
        print("========2: \(name) runs \(step) step.")
    }
}

添加方法

override func viewDidLoad() {
    super.viewDidLoad()
    _ = DYFSwiftRuntimeProvider.addMethod(withClass: ViewController.self, selector: Selector("eat(foods:)"), impClass: People.self, impSelector: #selector(People.eat(foods:)))
    perform(NSSelectorFromString("eat(foods:)"), with: ["name": "meat", "number": 1])
}

交换两个方法

override func viewDidLoad() {
    super.viewDidLoad()
    DYFSwiftRuntimeProvider.exchangeMethod(withClass: People.self, selector: #selector(People.run(step:)), anotherSelector: #selector(People.run2(step:)))
    let p = People(name: "Albert")
    p.run(step: 20)
    p.run2(step: 50)
    
    DYFSwiftRuntimeProvider.exchangeClassMethod(withClass: People.self, selector: #selector(People.decInfo2(age:name:)), anotherSelector: #selector(People.decInfo3(age:name:)))
    People.decInfo2(age: 50, name: "David")
    People.decInfo3(age: 26, name: "Liming")
}

替换方法

override func viewDidLoad() {
    super.viewDidLoad()
    DYFSwiftRuntimeProvider.replaceMethod(withClass: People.self, selector: #selector(People.run(step:)), targetSelector: #selector(People.run2(step:)))
    let p = People(name: "Albert")
    p.run2(step: 50)
}

交换两个方法(Swizzle)

override func viewDidLoad() {
    super.viewDidLoad()
    DYFSwiftRuntimeProvider.swizzleMethod(withClass: People.self, selector: #selector(People.run(step:)), swizzledSelector: #selector(People.run2(step:)))
    let p = People(name: "Albert")
    p.run(step: 20)
    p.run2(step: 50)
    
    DYFSwiftRuntimeProvider.swizzleClassMethod(withClass: People.self, selector: #selector(People.decInfo2(age:name:)), swizzledSelector: #selector(People.decInfo3(age:name:)))
    People.decInfo2(age: 50, name: "David")
    People.decInfo3(age: 26, name: "Liming")
}

动态替换实例和类方法

typealias IMPCType = @convention(c) (Any, Selector, Int) -> Void

private let newFunc: @convention(block) (Any, Int) -> Void = { (obj, age) in
    print("========obj: \(obj), age: \(age)")
    // Invoke the original method.
    let selector = #selector(People.logName(age:))
    ViewController.impBlock?(obj, selector, age)
}

typealias PEDecInfoIMPCType = @convention(c) (Any, Selector, Int, String) -> Void

private let peDecInfoFunc: @convention(block) (Any, Int, String) -> Void = { (obj, age, name) in
    print("====>obj: \(obj), age: \(age), name: \(name)")
}

override func viewDidLoad() {
    super.viewDidLoad()
    Self.impBlock = People.dy_replaceInstanceMethod(selector: #selector(People.logName(age:)), type: IMPCType.self, block: newFunc)
    _ = People.dy_replaceClassMethod(selector: #selector(People.decInfo(age:name:)), type: PEDecInfoIMPCType.self, block: peDecInfoFunc)
}

字典和模型的转换

以该类为例。例如:

class Teacher: NSObject {
    @objc var name: String?
    @objc var age: Int = 0
    @objc var address: String?
}

1. 将字典转换为模型

let teacher = DYFSwiftRuntimeProvider.asObject(with: ["name": "高粟", "age": 26, "address": "xx市xx"], for: Teacher.self)
if let teacher = teacher {
    print("========teacher: \(teacher), \(teacher.name), \(teacher.age), \(teacher.address)")
}
_ = DYFSwiftRuntimeProvider.asObject(withDictionary: ["name": "高粟", "age": 26, "address": "xx市xx"], forClass: Teacher.self)
_ = DYFSwiftRuntimeProvider.asObject(withDictionary: ["name": "高粟", "age": 26, "address": "xx市xx"], forObject: Teacher())

2. 将模型转换为字典

let teacher = Teacher()
teacher.name = "李想"
teacher.age = 22
teacher.address = "xxx"
let dict = DYFSwiftRuntimeProvider.asDictionary(withObject: teacher)
print("========dict: \(dict)")

归档和解归档

1. 归档

open class Transaction: NSObject, NSCoding {
    public func encode(with aCoder: NSCoder) {
        DYFSwiftRuntimeProvider.encode(aCoder, forObject: self)
    }
}

2. 解归档

open class Transaction: NSObject, NSCoding {
    public required convenience init?(coder aDecoder: NSCoder) {
        self.init()
        DYFSwiftRuntimeProvider.decode(aDecoder, forObject: self)
    }
}

添加类别属性

extension UIApplication {
    
    struct AssociatedObjcKeys {
        static var teacherKey = "TeacherKey"
    }
    
    var teacher: Teacher? {
        get {
            DYFSwiftRuntimeProvider.getAssociatedObject(self, key: &AssociatedObjcKeys.teacherKey) as? Teacher
        }
        set (objc) {
            DYFSwiftRuntimeProvider.setAssociatedObject(self, key: &AssociatedObjcKeys.teacherKey, value: objc, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
}

获取和修改实例变量属性

// for ViewController.
if let view = DYFSwiftRuntimeProvider.getInstanceVar(withName: "_view", forObject: self) as? UIView {
    view.backgroundColor = UIColor.brown
}

// Declares the var in ViewController.
var fillColor: UIColor = .white

if let fillColor = DYFSwiftRuntimeProvider.getInstanceVar(withName: "fillColor", forObject: self) as? UIColor {
    print("fillColor: \(fillColor)")
    if fillColor == .white {
        print("fillColor is white color.")
    }
}

DYFSwiftRuntimeProvider.setInstanceVar(withName: "fillColor", value: UIColor.brown, forObject: self)
print("self.fillColor: \(fillColor)")

欢迎反馈

如果您发现任何问题,请提交一个问题。我会很高兴帮助您。