簡體   English   中英

轉換非托管<anyobject> ! 布爾值 Swift</anyobject>

[英]Convert Unmanaged<AnyObject>! to Bool in Swift

我正在嘗試獲取現有目標 C class 的方法的結果,使用performSelector調用

let result = controlDelegate.performSelector("methodThatReturnsBOOL") as? Bool

我需要將此結果轉換為 Swift 的 Bool 類型。

上面提到的代碼,給出警告

“從'不受管理!' 不相關的類型 'Bool' 總是失敗”

結果始終為“false”,即使該方法返回 YES。

將結果轉換為 Bool 有什么建議嗎?

methodThatReturnsBOOL 的簽名

- (BOOL)methodThatReturnsBOOL
{
    return YES;
}

已經有很長一段時間了,因為這仍然沒有答案,所以我正在添加我在學習過程中學到的東西。

要轉換Objective C方法返回的BOOL值,您只需使用,

if let result = controlDelegate.performSelector("methodThatReturnsBOOL") {
    print("true")
} else {
    print("false")
}

如果需要,您還可以在此處將值true / false分配給Swift Bool

注意 :我嘗試使用takeRetainedValue()直接將Unmanaged<AnyObject>Bool如SO上的許多答案所示,但在這種情況下似乎不起作用。

這是Swift 3中的解決方案,因為方法有點不同。 此方法還檢查Objective-C對象是否響應選擇器,以避免崩潰。

import ObjectiveC

let selector = NSSelectorFromString("methodThatReturnsBOOL")

guard controlDelegate.responds(to: selector) else {
    return
}

if let result = controlDelegate.perform(selector) {
    print("true")
}
else {
    print("false")
}

你不能在Swift中做你想做的事。 我接受解決方案的問題在於它利用了0x0 恰好nil的想法。 Swift和Objective-C規范實際上並未保證這一點。 這同樣適用於布爾值,因為0x0為假,0x1為真只是一個任意的實現決策。 除了在技術上不正確之外,它也只是可怕的代碼才能理解。 在沒有考慮大多數平台上的nil指針(32/64位零)的情況下,所建議的是沒有意義的。

在WWDC '19與工程師談了一段時間后,他建議你實際上可以使用valueFor(forKey:) ,其中鍵是函數名稱/選擇器描述。 這是有效的,因為Obj-C運行時實際上將使用給定的名稱/鍵執行任何函數,以便計算表達式。 這仍然有點hacky,因為它需要了解Objective-C運行時,但是它保證是平台和實現獨立的,因為valueFor(forKey:)返回Any? 可以毫無困難地投入到IntBool 通過使用內置的強制轉換而不是推測0x0或0x1的含義,我們避免了解釋nil指針的整個問題。

例:

@objc func doThing() -> Bool{
    return true
}

...

let target = someObjectWithDoThing
let selectorCallResult = target.value(forKey: "doThing")

let intResult = selectorCallResult as? Int //Optional<Int(1)>
let boolResult = selectorCallResult as? Bool //Optional<Bool(true)>

與我在這里的回答相似,這可以通過@convention(c)來完成:

let selector: Selector = NSSelectorFromString("methodThatReturnsBOOL")
let methodIMP: IMP! = controlDelegate.method(for: selector)
let boolResult: Bool = unsafeBitCast(methodIMP,to:(@convention(c)(Any?,Selector)->Bool).self)(controlDelegate,selector)

這個特殊的語法從Swift 3.1開始可用,也可以在Swift 3中使用一個額外的變量。

更緊湊的轉換為 bool:

let result = controlDelegate.perform(NSSelectorFromString("methodThatReturnsBOOL")) != nil

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM