2017-02-14 55 views
1
let f:() -> Void = { } 

let array = ["a", 1, false, f] as [Any] 

if array[3] is AnyObject { 
    print(array[3]) 
} 

爲什麼元素爲AnyObject計算爲true,即使數組設置爲存儲Any?數組存儲任何對象也是AnyObject類型

爲什麼函數作爲AnyObject評估爲true,即使按定義AnyObject只能是類?

作爲另一個例子:

let f:() -> Bool = { return true } 
let ff = f as AnyObject 
(ff as() -> Bool)() 

這違背在API doc的AnyObject的定義,其中指出:

AnyObject可以用作具體類型爲任何 的一個實例類,類類型或僅類的協議。

或官方Swift Programming Language Guide

•任何可以在所有代表任何類型的實例,包括功能 類型。

•AnyObject可以表示任何類類型的實例。

在上面的例子中,它看起來像函數可以表示爲AnyObject。

SO中有其他地方的解釋(正如@hamish所指出的那樣),因爲在內部使用SwiftValue類,任何東西都可以橋接到AnyObject。解釋的邏輯似乎是有缺陷的/反向的,因爲我們應該使實現符合語言定義,而不是其他方式,所以要麼實現不正確,要麼AnyObject和類型檢查運算符的定義不正確?

+2

因爲* everything *是可橋接的到Swift 3中的'AnyObject'。參見[AnyObject不能在Xcode8 beta6中工作?](http://stackoverflow.com/q/39033194/2976878) – Hamish

+1

爲什麼以及如何將函數橋接到AnyObject?那不會打破AnyObject的定義嗎?即使可能,這種行爲似乎也是錯誤的。 – Boon

+2

閱讀鏈接的問答 - 直接與Obj-C不兼容的東西被裝箱在Objc-C兼容框中_SwiftValue。推理原因是因爲'id'現在被連接到Swift作爲'Any',所以'Any'需要可橋接回'id'。 – Hamish

回答

1

首先,Swift編程語言指南不是ISO 9899定義C的語言規範。(即使給定了ISO標準,也不是每個編譯器都以相同的方式實現C,甚至不是100%符合標準)如果你發現編譯器和文檔之間存在分歧,那麼它就像編譯器bug一樣可能是文檔錯誤。

儘管如此,我相信你已經掩蓋了該規範的一個重要組成部分,你參考:

AnyObject也可以用作具體類型爲橋樑,以一個Objective-一個類型的實例C類。 Swift橋中Objective-C中的許多值類型,如String和Int。

() -> Void相當於dispatch_block_t,這橋ObjC作爲dispatch_object(見dispatch/object.hos/object.h):

/* 
* By default, dispatch objects are declared as Objective-C types when building 
* with an Objective-C compiler. This allows them to participate in ARC, in RR 
* management by the Blocks runtime and in leaks checking by the static 
* analyzer, and enables them to be added to Cocoa collections. 
* See <os/object.h> for details. 
*/ 
OS_OBJECT_DECL_CLASS(dispatch_object); 

所以這裏沒有驚喜,() -> Void可強制轉換爲AnyObject

在實踐中,幾乎什麼現在可以縮小到AnyObject(再次,從來看,任何可以是NSValue可以是AnyObject語言規範點,儘管這不是它究竟是如何實現的)。但是,

AnyObject不同於AnyAny表現得像一個協議(儘管不是協議)。 AnyObject表現得像每個班級的超類(儘管實際上是一個協議)。

let b = true       // true 
let bany = true as Any    // true 
let banyobj = true as AnyObject  // 1 <=== (because it's NSNumber) 

MemoryLayout.size(ofValue: b)  // 1 (size of a bool) 
MemoryLayout.size(ofValue: bany)  // 32 (size of a protocol box) 
MemoryLayout.size(ofValue: banyobj) // 8 (size of a reference pointer) 

type(of: b)       // Bool.Type 
type(of: bany)      // Bool.Type 
type(of: banyobj)     // __NSCFBoolean.Type 

(嘗試同樣的事情{}看到封閉的處理方式。)

這是合理的打開對AnyObject文檔的缺陷,包括更明確的解釋,任何類型都可以轉換成一個使用as AnyObject的引用類型,但這只是一個遺漏,而不是已經存在的矛盾。 (如果這是一個矛盾,或者你覺得它很混亂,那麼正確的答案是打開一個缺陷來改善文檔以匹配Swift,而不是Swift來匹配文檔。)

+0

非常有見地,謝謝Rob! – Boon

相關問題