我正在嘗試在 Swift 中使用檔案 URL 捕獲 InputStream 的初始化。我已經成功地在 Objective-C 中為 NSInputStream 類實作了這樣的捕獲。問題是在交換初始化程式后,不會觸發 swizzled 方法。再者,方法交換后,直接呼叫swizzled方法并不會導致其執行,也就是說,其實作已成功交換。我想知道,這種奇怪行為的原因是什么,因為方法已成功混合,但尚不清楚,哪種方法被混合了。提供了當前在 Swift 中實作 InputStream swizzling 的示例。
private let swizzling: (AnyClass, Selector, Selector) -> () = { forClass, originalSelector, swizzledSelector in
if let originalMethod = class_getInstanceMethod(forClass, originalSelector),
let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector) {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
extension InputStream {
@objc dynamic func swizzledInit(url: URL) -> InputStream? {
print("Swizzled constructor")
return self.swizzledInit(url: url)
}
static func Swizzle() {
swizzling(InputStream.self, #selector(InputStream.init(url:)), #selector(swizzledInit(url:)))
}
}
uj5u.com熱心網友回復:
從InputStream檔案中:
NSInputStream是類簇NSStream的抽象超類,由提供對流資料的標準只讀訪問的具體子類組成。
這里的關鍵:當您創建一個 時InputStream,您回傳的物件將不是 型別InputStream,而是 的(私有)子類InputStream。與 Foundation 集合型別(NSArray/ NSMutableArray,NSDictionary/NSMutableDictionary等)非常相似,您與之互動的父型別不是您正在處理的有效 alloc型別:當您使用其中一種型別時,回傳的物件通常是私有子類的。
在大多數情況下,這是不相關的實作細節,但在您的情況下,因為您正在嘗試調配一個初始化程式,所以您確實關心從回傳的值,因為您正在調配一個 alloc從未被呼叫的初始化程式。
在特定情況下InputStream,從回傳的值 [NSInputStream alloc]屬于私有NSCFInputStream類,它是與 CoreFoundation 共享的有效免費橋接型別。這是可能隨時更改的私有實作細節,但您可以在該類上調整初始化程式:
guard let class = NSClassFromString("NSCFInputStream") else {
// Handle the fact that the class is absent / has changed.
return
}
swizzling(class, #selector(InputStream.init(url:)), #selector(swizzledInit(url:)))
請注意,如果您要提交應用以供 App Store 審核,則包含私有類名稱可能會影響審核程序。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/416824.html
標籤:
