我想加載和操縱SKUIImageColorAnalyzer
和 SKUIAnalyzedImageColors
對象來自私人StoreKitUI.framework
。公開在運行時從框架加載的類的接口
首先,我試圖在運行時加載框架:
guard case let libHandle = dlopen("/System/Library/PrivateFrameworks/StoreKitUI.framework/StoreKitUI", RTLD_NOW) where libHandle != nil else {
fatalError("StoreKitUI not found")
}
然後,我驗證SKUIImageColorAnalyzer
類,可以發現:
guard let analyzerClass: AnyClass = NSClassFromString("SKUIImageColorAnalyzer") else {
fatalError("SKUIImageColorAnalyzer lookup failed")
}
我想在使用analyzeImage:
類方法SKUIImageColorAnalyzer
,它需要UIImage
進行分析並返回SKUIAnalyzedImageColors
對象。我做這個通過驗證SKUIImageColorAnalyzer
對象上存在analyzeImage:
選擇,並重新創建功能:
let selector: Selector = "analyzeImage:"
guard case let method = class_getClassMethod(analyzerClass, selector) where method != nil else {
fatalError("failed to look up \(selector)")
}
// recreate the method's implementation function
typealias Prototype = @convention(c) (AnyClass, Selector, UIImage) -> AnyObject? // returns an SKUIAnalyzedImageColors object
let opaqueIMP = method_getImplementation(method)
let function = unsafeBitCast(opaqueIMP, Prototype.self)
現在,我可以得到一個UIImage
對象,並把它傳遞作爲參數傳遞給函數:
let img = UIImage(named: "someImage.jpg")!
let analyzedImageColors = function(analyzerClass, selector, img) // <SKUIAnalyzedImageColors: 0x7f90d3408eb0>
我知道analyzedImageColors
的類型是SKUIAnalyzedImageColors
,但編譯器仍然認爲它的類型是AnyObject
,這取決於我上面聲明Prototype
的方式。現在我想訪問一個SKUIAnalyzedImageColors
對象的屬性。
從header,我可以看到對象上有諸如backgroundColor
,textPrimaryColor
和textSecondaryColor
的屬性。我可以使用valueForKey
訪問這些屬性,但我想公開一個公共接口SKUIAnalyzedImageColors
,以便我可以訪問這些屬性。
我第一次嘗試這樣的:
// Create a "forward declaration" of the class
class SKUIAnalyzedImageColors: NSObject { }
// Create convenience extensions for accessing properties
extension SKUIAnalyzedImageColors {
func backgroundColor() -> UIColor {
return self.valueForKey("_backgroundColor") as! UIColor
}
func textPrimaryColor() -> UIColor {
return self.valueForKey("_textPrimaryColor") as! UIColor
}
func textSecondaryColor() -> UIColor {
return self.valueForKey("_textSecondaryColor") as! UIColor
}
}
// ...
// modify the prototype to return an SKUIAnalyzedImageColors object
typealias Prototype = @convention(c) (AnyClass, Selector, UIImage) -> SKUIAnalyzedImageColors?
// ...
// access the properties from the class extension
analyzedImageColors?.backgroundColor() // Optional(UIDeviceRGBColorSpace 0.262745 0.231373 0.337255 1)
這仍然要求我使用valueForKey
。有沒有辦法從運行時加載的框架暴露一個類的公共接口?
謝謝,但我真的在尋找一個純粹的Swift解決方案而不使用Objective-C。如果我想使用Objective-C,我可以從框架中取出標題並通過橋頭導入它們以暴露類和接口。 – JAL
此外,您純粹的Swift解決方案仍然需要我通過協議公開接口。有沒有辦法動態加載該對象的接口,而不是必須手動聲明所有內容? – JAL
儘管我很欣賞你的反思方法,不管。 – JAL