Site logo
Authors
  • avatar Nguyễn Đức Xinh
    Name
    Nguyễn Đức Xinh
    Twitter
Published on
Published on

Tìm Hiểu Optional Trong Swift

Optional là gì?

Optional trong Swift là một khái niệm quan trọng để xử lý các giá trị có thể có hoặc không có(nil). Nó giúp tránh các lỗi runtime do truy cập vào các biến chưa được khởi tạo hoặc các giá trị không tồn tại. Optional được biểu diễn bằng dấu hỏi chấm (?) sau kiểu dữ liệu.

Ví dụ : Bạn có một biến lưu email của người dùng. Trong trường hợp người dùng chưa nhập email, biến đó có thể là nil.

var userEmail: String? // Biến này có thể chứa một chuỗi hoặc không chứa gì (nil).

Tại sao sử dụng Optional?

  • Tránh lỗi runtime: Optional giúp bạn kiểm tra xem một giá trị có tồn tại trước khi sử dụng nó, giúp tránh các lỗi như nil pointer exception.
  • Làm cho code an toàn hơn: Optional giúp bạn viết code rõ ràng hơn và dễ bảo trì hơn.
  • Xử lý các trường hợp không chắc chắn: Optional rất hữu ích khi làm việc với dữ liệu từ các nguồn bên ngoài như API hoặc dữ liệu từ người dùng.

Cú Pháp Optional

Bạn sử dụng dấu chấm hỏi (?) để khai báo một biến có kiểu dữ liệu là Optional. 2.1. Ví dụ Khai Báo Optional

var age: Int? // Biến có thể là Int hoặc nil
age = 25
age = nil

2.2. Optional và Non-Optional

  • Non-Optional : Biến luôn chứa giá trị, không bao giờ là nil.
  • Optional : Biến có thể chứa giá trị hoặc không có gì (nil).
var name: String = "John" // Non-Optional
var nickname: String? = nil // Optional

Optional Binding

Trước khi sử dụng một giá trị Optional, bạn cần kiểm tra nó có chứa giá trị hay không. 3.1. Dùng Câu Lệnh if-let Câu lệnh if let: Kiểm tra xem optional có giá trị hay không, nếu có thì gán giá trị đó cho một hằng số hoặc biến mới. Câu lệnh if-let được sử dụng để unwrap (mở bọc) Optional, tức là lấy giá trị ra khỏi Optional một cách an toàn.

var optionalName: String? = "Alice"

if let name = optionalName {
    print("Hello, \(name)!")
} else {
    print("No name provided.")
}
// Kết quả: Hello, Alice!

3.2. Dùng Câu Lệnh guard-let guard-let tương tự như if-let, nhưng thường được sử dụng để thoát sớm khỏi một hàm hoặc khối lệnh nếu giá trị là nil.

func greetUser(optionalName: String?) {
    guard let name = optionalName else {
        print("Name is missing!")
        return
    }
    print("Hello, \(name)!")
}

greetUser(optionalName: "Bob") // Kết quả: Hello, Bob!
greetUser(optionalName: nil)  // Kết quả: Name is missing!

Forced Unwrapping

Bạn có thể dùng dấu chấm than (!) để ép mở bọc một Optional. Tuy nhiên, nếu giá trị là nil, ứng dụng sẽ gặp lỗi trong runtime (crash). 4.1. Ví dụ Forced Unwrapping

var number: Int? = 10
print(number!) // Kết quả: 10

number = nil
// print(number!) // Lỗi runtime: Unexpectedly found nil while unwrapping an Optional value

Lưu ý : Chỉ sử dụng ! khi bạn chắc chắn rằng Optional không phải là nil.

Optional Chaining:

Sử dụng dấu chấm hỏi (?) để truy cập vào các thuộc tính hoặc gọi các phương thức của một optional. Nếu optional là nil, chuỗi truy cập sẽ dừng lại và trả về nil.

let address = person?.address?.street

Optional Chaining

Optional Chaining sử dụng dấu chấm hỏi (?) để truy cập vào các thuộc tính hoặc gọi các phương thức của một optional. Nếu optional là nil, chuỗi truy cập sẽ dừng lại và trả về nil. Đây là một cách an toàn để gọi thuộc tính, phương thức hoặc chỉ số của một Optional. 5.1. Ví dụ Optional Chaining

class Person {
    var name: String
    var address: Address?
    
    init(name: String) {
        self.name = name
    }
}

class Address {
    var street: String
    
    init(street: String) {
        self.street = street
    }
}

let john = Person(name: "John")
john.address = Address(street: "123 Main St")

if let street = john.address?.street {
    print("Street: \(street)")
} else {
    print("No address available.")
}
// Kết quả: Street: 123 Main St

Nil-Coalescing Operator (Toán Tử ??)

Toán tử ?? cho phép bạn cung cấp một giá trị mặc định khi Optional là nil. 6.1. Cú Pháp

let optionalValue: String? = nil
let defaultValue = optionalValue ?? "Default Value"
print(defaultValue) // Kết quả: Default Value

Implicitly Unwrapped Optionals

Implicitly Unwrapped Optionals (Optional mở bọc ngầm) là những Optional mà bạn không cần phải mở bọc thủ công, nhưng phải đảm bảo rằng chúng luôn có giá trị trước khi sử dụng. 7.1. Ví dụ

var implicitlyUnwrappedString: String! = "Hello"
print(implicitlyUnwrappedString) // Kết quả: Hello

implicitlyUnwrappedString = nil
// print(implicitlyUnwrappedString) // Lỗi runtime nếu giá trị là nil

Lưu ý : Sử dụng kiểu này cẩn thận vì nó dễ gây lỗi runtime.

So Sánh Optional với Non-Optional

Đặc Điểm Non-Optional Optional
Giá trị Luôn luôn có giá trị Có thể chứa giá trị hoặc nil
Khai báo Không dùng dấu ? Dùng dấu ? hoặc !
An toàn An toàn hơn Yêu cầu kiểm tra hoặc mở bọc trước khi sử dụng

Khi Nào Sử Dụng Optional?

  • Khi một biến có thể không có giá trị.
  • Khi bạn làm việc với các API trả về giá trị không chắc chắn (như tìm kiếm một phần tử).
  • Khi bạn cần đại diện cho các trạng thái như "không được khởi tạo" hoặc "dữ liệu bị thiếu".

Kết Luận

Optional giúp lập trình viên quản lý các giá trị không xác định một cách an toàn và rõ ràng. Thay vì gặp lỗi runtime do null, bạn có thể kiểm soát chặt chẽ hơn các trường hợp giá trị không tồn tại. Bằng cách nắm vững Optional, bạn sẽ tránh được nhiều lỗi phổ biến và xây dựng mã dễ bảo trì hơn trong các dự án Swift của mình.

Bài Tập Thực Hành

Hãy thực hành để hiểu rõ hơn về Optional bằng cách giải các bài tập sau:

  1. Tạo một hàm tính chiều dài của chuỗi, trả về nil nếu chuỗi rỗng.
func stringLength(_ input: String?) -> Int? {
    guard let input = input, !input.isEmpty else {
        return nil
    }
    return input.count
}
  1. Sử dụng Optional Chaining để truy xuất thông tin từ một lớp chứa các Optional.
  2. Viết hàm kiểm tra số lẻ hay số chẵn, trả về nil nếu số đầu vào không hợp lệ.