Swift Optional Type
Kiểu Optional : cho phép gán nil Không phải kiểu Optional : không cho phép gán nil var a : Int ? // Kiểu Optional var b : Int // Không phải kiểu Optional var c : String ? // Kiểu Optional var d : String // Không phải kiểu Optional var a : Int ? ...
- Kiểu Optional : cho phép gán nil
- Không phải kiểu Optional : không cho phép gán nil
var a: Int? // Kiểu Optional var b: Int // Không phải kiểu Optional var c: String? // Kiểu Optional var d: String // Không phải kiểu Optional
var a: Int? var b: Optional<Int> // tương đương với Int?
var a: Int? // Kiểu Optional a = nil // Không phát sinh compile error var b: Int // Không phải kiểu optional b = nil // Compile error : Could not find an overload for '__conversion' that accepts the supplied arguments
Giá trị khởi tạo của kiểu Optional là nil.
var a: Int? // Kiểu Optional println(a) // -> nil
Nếu không phải là kiểu Optional thì không có gì trong giá trị khởi tạo (không có cả nil)
var b: Int // Không phải kiểu Optional println(b) // Compile error: Variable 'b' used before being initialized
var a: Int = 1 println(a + 2) // -> 3 var b: Int? = 1 println(b + 2) // Compile error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
Theo như trên, thì Int? là kiểu khác với Int nên không thể thao tác giống vây được. để có thể xử lý giống với Int thì cần phải unwrap.(mô tả bên dưới).
【Đang được wrap】là gì?
Biến số có kiểu Optional (kiểu Optional<T>) gọi là『đang được wrap』.
【Unwrap】?
Việc lấy ra biến kiểu T từ kiểu Optional(kiểu Optional<T>)được gọi là 『Unwrap』.
Có những phương pháo dưới dùng để unwrap biến kiểu Optional
- Forced Unwrapping
- Optional Chaining
- Optional Binding
- Implicitly Unwrapped Optional Type
1. Forced Unwrapping
Sử dụng ! như dưới đây để có thể unwrap biến kiểu Optional.
class Dog { func bark() -> String { return "Wan!" } } var d: Dog? = Dog() // Kiểu Optional // Không thể call method bark nếu vẫn là trạng thái đã wrap println(d.bark()) // Compile error: 'Dog?' does not have a member named 'bark' // Có thể unwrap bằng cách thêm 「!」 vào sau biến d (Forced Unwrapping) println(d!.bark()) // -> Wan! // Nếu biến d là nil thì sẽ phát sinh runtime error khi unwrap bằng 「!」 d = nil println(d!.bark()) // Runtime error: fatal error: Can't unwrap Optional.None
2. Optional Chaining
Sử dụng ? chứ không phải ! như bên dưới đây để unwrap.
class Dog { func bark() -> String { return "Wan!" } } var d: Dog? = Dog() // Kiểu Optional // Nếu thêm 「?」 vào phía sau biến d thì sẽ unwrap (Optional Chaining) println(d?.bark()) // -> Wan! // Nếu biến d là nil thì unwrap sẽ trả lại nil d = nil println(d?.bark()) // -> nil
Khác với Forced Unwrapping, cho dù unwrap cho nil thì cũng không phát sinh runtime error, mà thay vào đó sẽ trả về nil.
Chú ý: về println
Kết quả output của println(d?.bark()) sẽ khác với xcode version mới nhất nên phải chú ý.
- Nếu là Xcode 6 Beta(version đã sử dụng để viết trong bài này) println(d?.bark()) // -> Wan!
- Nếu là Xcode 6.1 GM seed 2 println(d?.bark()) // -> Optional(Wan!)
Khi output variable kiểu optional bằng println thì chuỗi Optional() sẽ được thêm vào.
3. Optional Binding
Biến được gán bằng kiểu Optional mà được khai báo trong biểu thức điều kiện IF hay WHILE thì trở thành kiểu không phải là Optional.
class Dog { func bark() -> String { return "Wan!" } } var wrappedDog: Dog? = Dog() // Kiểu Optional // Biến được khai báo trong câu IF sẽ trở thành không phải kiểu Optional(Optional Binding) if var unwrappedDog1 = wrappedDog { // Không cần phải thêm「!」 println(unwrappedDog1.bark()) // -> Wan! } // Khai báo「var」と「let」đều được if let unwrappedDog2 = wrappedDog { println(unwrappedDog2.bark()) // -> Wan! } // Có thể sử dung Optional Binding trong câu WHILE while var unwrappedDog3 = wrappedDog { println(unwrappedDog3.bark()) // -> Wan! break } /////////////// // Bổ sung 1 // /////////////// // // Các biến「unwrappedDog1」「unwrappedDog2」「unwrapedDog3」 bên trên chỉ hữu hiệu trong block // println(unwrappedDog1.bark()) // Compile error: Use of unresolved identifier 'unwrappedDog1' println(unwrappedDog2.bark()) // Compile error: Use of unresolved identifier 'unwrappedDog2' println(unwrappedDog3.bark()) // Compile error: Use of unresolved identifier 'unwrappedDog3' /////////////// // Bổ sung 2 // /////////////// // // Trong trường hợp wrappedDog là nil, kết quả của điều kiện câu IF là false nên ko thực hiện xử lý trong block // wrappedDog = nil if var unwrappedDog4 = wrappedDog { // false println("This is not printed out.") // -> không output gì }
4. Kiểu Implicitly Unwrapped Optional
Nếu sử dụng kiểu Implicitly Unwrapped Optional chứ không phải kiểu Optional(Optional<T>) thì có thể unwrap ngầm. Khi khai báo biến kiểu Implicitly Unwrapped Optional thì sử dụng ! chứ không phải ?.
class Dog { func bark() -> String { return "Wan!" } } // Khai báo bằng 「!」chứ ko phải bằng「?」 var d: Dog! = Dog() // Kiểu Implicitly Unwrapped Optional // Không cần thực hiện unwrap(đã unwrap ngầm) println(d.bark()) // -> Wan! // Nếu biến d là nil, khi unwrap ngầm sẽ bị runtime error d = nil println(d.bark()) // Runtime error: fatal error: Can't unwrap Optional.None
var a: Int! // Kiểu Implicitly Unwrapped Optional var b: ImplicitlyUnwrappedOptional<Int> // Tương đương với Int!
Type | Khai báo | Entity of type | Thao tác khi unwrap |
---|---|---|---|
Optional | var a: T? | Optional<T> | Cần thao tác rõ ràng |
Implicitly Unwrapped Optional | var a: T! | ImplicitlyUnwrappedOptional<T> | Không cần (được unwrap ngầm) |
Trường hợp là kiểu Optional (Optional<T>)
Phương pháp unwrap | Kết quả |
---|---|
Trường hợp là Forced Unwrapping (phương pháp sử dụng !) | Phát sinh runtime error |
Trường hợp là Optional Chaining (phương pháp sử dụng ?) | Trả về nil |
class Dog { func bark() -> String { return "Wan!" } } var d: Dog? = nil // Kiểu Optional // Trường hợp Forced Unwrapping (sử dụng !) println(d!.bark()) // Runtime error: fatal error: Can't unwrap Optional.None // Trường hợp Optional Chaining (Sử dụng ?) println(d?.bark()) // -> nil
Trường hợp là kiểu Implicitly Unwrapped Optional (ImplicitlyUnwrappedOptional<T>)
Phương pháp unwrap | Kết quả |
---|---|
Unwrap ngầm | Phát sinh runtime error |
class Dog { func bark() -> String { return "Wan!" } } var d: Dog! = nil // Kiểu Implicitly Unwrapped Optional println(d.bark()) // Runtime error: fatal error: Can't unwrap Optional.None
Develop enviroment
Xcode 6 Beta
Mac OS X 10.9.3
Run enviroment
iOS Simulator (iPhone5s / iOS 8.0)
Source: http://qiita.com/cotrpepe/items/e30c7442733b93adf46a