2015-04-14 11 views
36

Zanim przeniesieni do Swift 1.2, mogę napisać następującą linię:Jaka jest różnica między "as?", "As!" I "as"?

if let width = imageDetails["width"] as Int? 

Teraz zmusza mnie do napisania tego wiersza:

if let width = imageDetails["width"] as! Int? 

Moje pytanie brzmi, czy jestem zmuszony pisać tak jak powyżej, czy nie mógłbym napisać kodu poniżej i zrobiłby to samo? Czy dałby mi taki sam wynik we wszystkich wartościach imageDetails?

if let width = imageDetails["width"] as Int 

Odpowiedz

49

AS hasła czynili zarówno upcasts i downcasts:

// Before Swift 1.2 
var aView: UIView = someView() 

var object = aView as NSObject // upcast 

var specificView = aView as UITableView // downcast 

The uskok, począwszy od klasy pochodnej do klasy bazowej, mogą być sprawdzane w czasie kompilacji i nigdy nie zawodzą.

Jednak odrzucenia mogą się nie udać, ponieważ nie zawsze można być pewnym danej klasy. Jeśli masz UIView, możliwe, że jest to UITableView lub może UIButton. Jeśli twój downcast idzie do właściwego typu - świetnie! Ale jeśli zdarzy ci się określić niewłaściwy typ, dostaniesz błąd runtime i aplikacja się zawiesi.

W Swift 1.2, downcasts musi być opcjonalny z as? lub "wymuszony failable" z as !. Jeśli masz pewność co do typu, możesz wymusić obsadę jako! podobny do tego, jak byłoby użyć niejawnie-rozpakowany opcjonalnie:

// After Swift 1.2 
var aView: UIView = someView() 

var tableView = aView as! UITableView 

Wykrzyknik sprawia, że ​​absolutnie jasne, że wiesz co robisz i że istnieje szansa, wszystko pójdzie bardzo źle, jeśli już przypadkowo mieszane Twoje typy!

Jak zwykle, jako? z opcjonalnym wiązania jest najbezpieczniejszym sposobem, aby przejść:

// This isn't new to Swift 1.2, but is still the safest way 
var aView: UIView = someView() 

if let tableView = aView as? UITableView { 
    // do something with tableView 
} 

Got to ze strony: SOURCE

+0

Dzięki Jacobson! Jedno dodatkowe pytanie - czasami wpadam w zakłopotanie pomiędzy downcastingiem a wersją Int "konwertującą" do Float. Jeśli masz wartość Integer, ale chcesz przekonwertować na Float, czy został downcast lub konwersji? A co z pływającym o wartości całkowitej? (tj. 2.0) – Alex

0

Prawidłowa idiom, który powinien zrobić dokładnie to, co chcesz (we wszystkich wersjach Swift przynajmniej do września włącznie 1.2) jest opcjonalnym rzutowaniem as?.

if let width = imageDetails["width"] as? Int 

Opcjonalny odlew zwraca opcjonalny (w tym przypadku w tym przypadku) i jest testowany w czasie wykonywania. Twój oryginalny kod prawdopodobnie wymusił rzutowanie na opcjonalny typ.

36

as

Swift 1.2, a następnie, as mogą być wykorzystywane tylko dla upcasting (lub ujednoznacznienie) i dopasowane wzór:

// 'as' for disambiguation 
let width = 42 as CGFloat 
let block = { x in x+1 } as Double -> Double 
let something = 3 as Any? // optional wrapper can also be added with 'as' 


// 'as' for pattern matching 
switch item { 
case let obj as MyObject: 
    // this code will be executed if item is of type MyObject 
case let other as SomethingElse: 
    // this code will be executed if item is of type SomethingElse 
... 
} 

as?

The Operator warunkowy obsada as? próbuje wykonać konwersję, ale zwraca nil, jeśli nie może. Zatem jego wynik jest opcjonalny.

let button = someView as? UIButton // button's type is 'UIButton?' 

if let label = (superview as? MyView)?.titleLabel { 
    // ... 
} 

as!

Operator as! jest zmuszony rodzaj konwersji.

pomocą wymuszonego formę operatora typ odlewu (as!) tylko wtedy, gdy jesteś pewienże przygnębiony zawsze uda. Ta forma operatora wyzwoli błąd runtime error, jeśli spróbujesz obniżyć do niewłaściwego typu klasy.

// 'as!' for forced conversion. 
// NOT RECOMMENDED. 
let buttons = subviews as! [UIButton] // will crash if not all subviews are UIButton 
let label = subviews.first as! UILabel 
+1

Dzięki @jtbandes. Ta odpowiedź jest lepsza niż zaakceptowana odpowiedź. – hujunfeng

+0

'as?' Może być również używany do upcastingu (jak również downcastingu), więc wydaje mi się, że posiadanie zarówno 'as' jak i' as? 'Do upcastingu jest zbędne. Apple Swift Guide nawet nie wspomina o "as" do castingu. – 7stud

+0

W odpowiedzi na 7stud, robi to różnicę, gdy robisz coś takiego jak wpisanie literału: biorąc pierwszy przykład z odpowiedzi "niech szerokość = 42 jako? CGFloat' produkuje 'Opcjonalne ', natomiast 'let width = 42 jako CGFloat' to po prostu' CGFloat'. Nie ma żadnego powodu, aby używać opcjonalnego; wartość jest gwarantowana. –