RuntimeKit 0.5.0

RuntimeKit 0.5.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布上次发布2017年5月
SwiftSwift 版本3.0
SPM支持 SPM

Lukas Kollmer维护。



RuntimeKit

RuntimeKit是一个用于访问Objective-C运行时的Swift库。它除了提供method swizzling或关联值等特性包装外,还提供了一些类型安全。

到目前为止,RuntimeKit支持method swizzling,用块替换方法实现,设置关联对象,查找对象属性,向现有类添加新方法以及创建新类和协议。未来还将添加更多功能。

安装

CocoaPods (推荐)

pod 'RuntimeKit'

从源码编译

只需将RuntimeKit/Sources中的所有内容复制到您的Xcode项目中

特性

  1. 方法交换
  2. 关联对象
  3. 创建新类
  4. 创建新协议
  5. 进行带有额外类型安全性的Objective-C选择器操作

方法交换

交换两个方法的实现

extension NSDate {
    func xxx_addingTimeInterval(_ ti: TimeInterval) -> NSDate {
        print("will add \(ti)")
        return self.xxx_addingTimeInterval(ti)
    }   
}

try! NSDate.swizzle(#selector(NSDate.addingTimeInterval(_:)), with: #selector(NSDate.xxx_addingTimeInterval(_:)))

NSDate().addingTimeInterval(100) // prints "will add 100"

用块替换方法的实现

let systemFontOfSize_block: @convention(block) (UIFont, Selector, CGFloat) -> UIFont = { (self, sel, size) in
    return UIFont(name: "Avenir-Book", size: size)!
}

try! UIFont.replace(#selector(UIFont.systemFont(ofSize:)), withBlock: systemFontOfSize_block, methodType: .class)

let systemFont = UIFont.systemFont(ofSize: 15) // -> <UICTFont: 0x7fddc5703150> font-family: "Avenir-Book"; font-weight: normal; font-style: normal; font-size: 15.00pt>

关联对象

extension AssociatedObjectKeys {
    static let name = AssociatedObjectKey<String>("name")
    static let age  = AssociatedObjectKey<Int>("age")
}

class Person: NSObject {}

let me = Person()
me.setAssociatedObject("Lukas", forKey: .name)
me.setAssociatedObject(18, forKey: .age)

let name = me.getAssociatedObject(forKey: .name) // Optional("Lukas")
let age  = me.getAssociatedObject(forKey: .age)  // Optional(18)

创建新类

let LKGreeter = try! Runtime.createClass("LKGreeter")

let greetMethod_block: @convention(block) (NSObject, Selector, String) -> String = { (_self, _sel, name) in
    return "Hello, \(name)"
}

try! LKGreeter.addMethod("greet", implementation: greetMethod_block, methodType: .class, returnType: .object, argumentTypes: [.object, .selector, .object])

LKGreeter.perform("greet", with: "Lukas").takeRetainedValue() // result: "Hello, Lukas"

创建新协议

let methods = [
    ObjCMethodDescription("greet", returnType: .object, argumentTypes: [.object, .selector, .object], methodType: .class, isRequired: true)
]

let GreeterProtocol = try! Runtime.createProtocol("Greeter", methods: methods)
let LKGreeter = try! Runtime.createClass("LKGreeter", superclass: NSObject.self, protocols: [GreeterProtocol])

进行带有额外类型安全性的Objective-C选择器操作

let formatBlock: @convention(block) (NSDate, Selector, String) -> String = { (_self, _sel, format) in
    let formatter = DateFormatter()
    formatter.dateFormat = format
    return formatter.string(from: _self as Date)
}
try! NSDate.addMethod("customFormat:", implementation: formatBlock, methodType: .instance, returnType: .object, argumentTypes: [.object, .selector, .object])

extension ObjCMethodCallRequests {
    static let customFormat = ObjCMethodCallRequest<String>("customFormat:")
}

let now = NSDate()
let formatString: String = try! now.perform(.customFormat, "EEEE MMM d, yyyy") // -> "Saturday Apr 1, 2017"