测试已测试 | ✗ |
Lang语言 | SwiftSwift |
许可证 | MIT |
发布上次发布 | 2017年5月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由Lukas Kollmer维护。
RuntimeKit是一个用于访问Objective-C运行时的Swift库。它除了提供method swizzling或关联值等特性包装外,还提供了一些类型安全。
到目前为止,RuntimeKit支持method swizzling,用块替换方法实现,设置关联对象,查找对象属性,向现有类添加新方法以及创建新类和协议。未来还将添加更多功能。
CocoaPods (推荐)
pod 'RuntimeKit'
从源码编译
只需将RuntimeKit/Sources
中的所有内容复制到您的Xcode项目中
交换两个方法的实现
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])
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"