GetWild退勤的なセンサーアプリを簡単に作れるフレームワークを作ったのでiPhoneに歯痛を心配されたり色々する
で得た知見シリーズ
文字列のクラス名からインスタンスを生成する
public func NSClassFromString(aClassName: String) -> AnyClass?
を使う。
@objc(Hoge)
class Hoge: NSObject, FugaProtocol {
}
let className = "Hoge"
let cls = NSClassFromString(className) as! NSObject.Type
instance = (cls.init() as! FugaProtocol)
生成対象にするクラスはNSObjectを継承していて、かつ@objcを付けていないといけない。
動的にpropertyを追加する
public func objc_setAssociatedObject(object: AnyObject!, _ key: UnsafePointer<Void>, _ value: AnyObject!, _ policy: objc_AssociationPolicy)
と
public func objc_getAssociatedObject(object: AnyObject!, _ key: UnsafePointer<Void>) -> AnyObject!
を使う
import Foundation
protocol dynamicStoredPropertyProtocol {
func setDynamicStoredProperty(propertyName: String, propertyValue: AnyObject)
func getDynamicStoredProperty(propertyName: String) -> AnyObject?
}
extension dynamicStoredPropertyProtocol where Self: NSObject {
func setDynamicStoredProperty(propertyName: String, propertyValue: AnyObject) {
if !hasDynamicStoredPropertyContainer() {
initDynamicStoredPropertyContainer()
}
var container = getDynamicStoredPropertyContainer()
container![propertyName] = propertyValue
setDynamicStoredPropertyContainer(container!)
}
func getDynamicStoredProperty(propertyName: String) -> AnyObject? {
guard var container = getDynamicStoredPropertyContainer() else {
return nil
}
return container[propertyName]
}
func initDynamicStoredPropertyContainer() {
setDynamicStoredPropertyContainer([:])
}
func setDynamicStoredPropertyContainer(container: Dictionary<String, AnyObject>) {
objc_setAssociatedObject(self, &containerPointer, container, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
func getDynamicStoredPropertyContainer() -> Dictionary<String, AnyObject>? {
return objc_getAssociatedObject(self, &containerPointer) as? Dictionary<String, AnyObject>
}
func hasDynamicStoredPropertyContainer() -> Bool {
guard (getDynamicStoredPropertyContainer() != nil) else {
return false
}
return true
}
}
private var containerPointer:UInt8 = 0
元気とランタイムAPIがあれば何でもできる。
ここまで書いておいてあれだけれど、コンパイル時に分からず実行してみないと分からない事が増えたり、計測してないけどランタイムAPIを使うとパフォーマンスどうなんだろうという懸念があったりするので、普通のアプリケーションでは使わない方が良いと思う。