2016-06-29 15 views
0

Hier ist mein Code:Warum kann der Swift-Compiler den Typ eines Elements in einem gemischten Array nicht herausfinden?

let string: String = "hello" 
let int: Int = 5 
let double: Double = 3.14 

let mixedTypeArray = [string, int, double] 
let elementOfApparentlyUnknownType = mixedTypeArray[0] // AnyObject 

ich sehr explizit die Typen von jedem Element in dem Mischtyp-Array mixedTypeArray angegeben haben. Wenn das erste Element im Array abgerufen wird, leitet der Compiler das Element jedoch nicht als String ab. Stattdessen ist es vom Typ AnyObject.

mixedTypeArray ist ein NSArray, da Swift nativen Array Typ erlaubt keine Elemente unterschiedlichen Typs Speicherung (es sei denn, sie alle zu AnyObject umgewandelt sind, aber das würde Typinformationen verlieren). Aber wenn NSArray ist cool mit Speichern von Elementen verschiedener Typen, warum ist mixedTypeArray[0] des Typs AnyObject? Ist NSArray alle Elemente in AnyObject hinter den Kulissen umwandeln? Gibt es eine Möglichkeit, den richtigen Typ von mixedTypeArray[0] zur Kompilierzeit zu erhalten? Ich möchte vermeiden, jedes Element einzeln in mixedTypeArray von AnyObject auf seinen tatsächlichen Typ zu reduzieren.

Antwort

3

Schnelle Arrays enthalten nur einen Typ. Im reinen Swift-Code würde Ihr Beispiel nicht einmal kompilieren. Sie würden den Fehler erhalten: Fehler: Art des Ausdrucks ist mehrdeutig ohne mehr Kontext.

Sie Code kompiliert wird, weil Sie Foundation importiert haben, entweder weil Sie explizit import Foundation angegeben, oder weil Sie UIKit oder Cocoa von denen jeder importiert Foundation importiert.

Wenn Foundation importiert wird, werden gemischte Arrays als NSArray behandelt, was im Wesentlichen dasselbe ist wie [AnyObject]. Dies bedeutet, dass alles, was in dieses Array eingefügt wird, eine Instanz einer Klasse sein muss. Da String eine Struktur ist und Int und Double primitive Typen sind, sind sie keine Klassen. Die String wird zu NSString befördert, und die Int und Double werden in NSNumber verpackt.

Sie können das sehen, wenn Sie die dynamicTypes der Werte ausdrucken:

print(mixedTypeArray[0].dynamicType) // _NSContiguousString 
print(mixedTypeArray[1].dynamicType) // __NSCFNumber.Type 
print(mixedTypeArray[2].dynamicType) // __NSCFNumber.Type 

_NSContiguousString ist eine interne Darstellung eines NSString. __NSCFNumber.Type ist eine interne Darstellung von NSNumber.

Aber das Array selbst enthält nur einen Typ: AnyObject.

Wenn Sie das tun:

let elementOfApparentlyUnknownType = mixedTypeArray[0] // AnyObject 

dann wird der Wert der Typ hat AnyObject, weil das ist, was das Array zu speichern. Swift schaut nicht, um zu sehen, dass das Element wirklich ein NSString ist, weil das eine Laufzeitüberlegung ist.Zur Kompilierungszeit verfolgt Swift nicht, dass Sie String in die Position 0 dieses Arrays setzen. Es weiß nur, dass dieses Array einen Typ NSString (auch bekannt als) hat.

Die Typen der Variablen sind zur Kompilierzeit in Swift bekannt. Sie können jederzeit Option - Klicken Sie auf eine Variable, um ihren Typ zu sehen. Aus diesem Grund besteht die beste Möglichkeit von Swift darin, die Variable AnyObject zu erstellen, da sie zur Kompilierungszeit die zugrunde liegenden Typen der Werte in Ihrem Array nicht kennt.

Sie könnten Ihr Array deklariert haben als Typen [Any] und dann die dynamicTypes Ihren Wert hätte String, Int und Double geblieben. Aber dann hätte jeder Array-Zugriff eine Variable vom Typ Any ergeben.

Swift leitet kein Array vom Typ [Any] ab. Es wird Ihnen nur das geben, wenn Sie ausdrücklich darum bitten. Als eine allgemeine Designregel, wenn Sie sich mit Any finden, nähern Sie sich wahrscheinlich das Problem in der falschen Weise.

0

In Swift müssen alle Array-Elemente den gleichen Typ haben. In diesem Fall haben alle Array-Elemente den Typ Any (nicht AnyObject, da Sie einen Wert vom Typ Int angegeben haben). Das erste Array-Element ist vom Typ Any, nicht vom Typ String. Die zweite ist vom Typ Any, nicht vom Typ Int. Und so weiter.