2015-04-14 32 views
36

Trước khi tôi nâng cấp lên Swift 1.2, tôi có thể viết những dòng sau:Sự khác biệt giữa "như?", "As!" Và "as" là gì?

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

Bây giờ nó buộc tôi viết dòng này:

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

Câu hỏi của tôi là, nếu tôi buộc phải viết nó như trên, tôi không thể chỉ viết mã dưới đây và nó sẽ làm điều tương tự? Nó sẽ cho tôi cùng một kết quả trong tất cả các giá trị của imageDetails?

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

Trả lời

49

Các từ khóa như sử dụng để làm cả hai upcasts và downcasts:

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

var object = aView as NSObject // upcast 

var specificView = aView as UITableView // downcast 

Các bị ném lên trời, đi từ một lớp được thừa kế một lớp cơ sở, có thể được kiểm tra tại thời gian biên dịch và sẽ không bao giờ thất bại.

Tuy nhiên, quá trình phát có thể không thành công do bạn không thể luôn chắc chắn về lớp học cụ thể. Nếu bạn có UIView, có thể đó là UITableView hoặc có thể là UIButton. Nếu downcast của bạn đi đúng loại - tuyệt vời! Nhưng nếu bạn tình cờ chỉ định loại sai, bạn sẽ gặp lỗi thời gian chạy và ứng dụng sẽ gặp sự cố.

Trong Swift 1.2, lịch phát sóng phải là tùy chọn với? hoặc "bắt buộc phải có" với như !. Nếu bạn chắc chắn về loại, thì bạn có thể ép buộc diễn viên bằng! tương tự như cách bạn sẽ sử dụng một tùy chọn ngầm-quà nào:

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

var tableView = aView as! UITableView 

Các dấu chấm than làm cho nó hoàn toàn rõ ràng rằng bạn biết những gì bạn đang làm và rằng có một cơ hội thứ sẽ gặp rắc rối hay nếu bạn đã vô tình trộn lẫn lên các loại của bạn!

Như mọi khi, như? với tùy chọn ràng buộc là cách an toàn nhất để đi:

// 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 này từ một trang web: SOURCE

+0

Cảm ơn Jacobson! Một câu hỏi bổ sung - đôi khi tôi bị nhầm lẫn giữa downcasting với một phiên bản Int "chuyển đổi" thành Float. Nếu bạn có giá trị Số nguyên nhưng bạn muốn chuyển đổi thành Float, bạn có bị downcast hoặc chuyển đổi không? Điều gì về một Float với một giá trị số nguyên? (ví dụ: 2.0) – Alex

0

Các thành ngữ đúng khi cho rằng nên thực hiện chính xác những gì bạn muốn (trong tất cả các phiên bản của Swift ít nhất tối đa và bao gồm 1.2) là as? tùy chọn truyền.

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

Truyền tùy chọn trả về tùy chọn (Int? Trong trường hợp này) và được kiểm tra trong thời gian chạy. Mã ban đầu của bạn có thể buộc một diễn viên vào loại tùy chọn.

36

as

Trong Swift 1.2 và sau đó, as chỉ có thể được sử dụng cho upcasting (hoặc định hướng) và mô hình phù hợp với:

// '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?

Các có điều kiện nhà điều hành truyền as? cố gắng thực hiện chuyển đổi, nhưng trả lại nil nếu không thể. Do đó kết quả của nó là tùy chọn.

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

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

as!

Nhà điều hành as! là dành cho buộc loại chuyển đổi.

Sử dụng các hình thức buộc của người điều khiển loại cast (as!) chỉ khi bạn đang chắc chắn rằng nhìn xuống sẽ luôn thành công. Biểu mẫu này của nhà điều hành sẽ kích hoạt lỗi thời gian chạy nếu bạn cố gắng chuyển sang loại lớp không chính xác.

// '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

Cảm ơn @jtbandes. Câu trả lời này tốt hơn câu trả lời được chấp nhận. – hujunfeng

+0

'as?' Cũng có thể được sử dụng cho upcasting (cũng như downcasting), do đó, có vẻ như với tôi rằng có cả 'as' và' as? 'Cho upcasting là thừa. Hướng dẫn Swift của Apple thậm chí còn không đề cập đến 'as' để truyền. – 7stud

+0

Để trả lời 7stud, nó tạo sự khác biệt khi bạn đang làm một cái gì đó như gõ chữ: lấy ví dụ đầu tiên từ câu trả lời 'let width = 42 as? CGFloat' tạo ra một 'Tùy chọn ', trong khi 'let width = 42 là CGFloat' chỉ là một' CGFloat'. Không có lý do chính đáng để sử dụng tùy chọn ở đó; giá trị được đảm bảo. –

Các vấn đề liên quan