Optional trong Swift: hiểu đúng để không còn sợ dấu chấm hỏi và chấm than

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Với người mới học Swift, dấu chấm hỏi và chấm than đi kèm kiểu dữ liệu là điều khó hiểu nhất. Thực ra Optional là một thiết kế thông minh giúp tránh lỗi giá trị rỗng. Hiểu bản chất của nó, bạn sẽ viết code iOS an toàn hơn nhiều.

Optional là gì?

Optional là kiểu dữ liệu biểu diễn một giá trị có thể có hoặc không có (nil). Hãy hình dung nó là cái hộp: bên trong có thể chứa một giá trị hoặc rỗng. Bạn phải mở hộp (unwrap) kiểm tra rồi mới dùng.

var nickname: String? = nil   // chưa có biệt danh
nickname = "Bem"              // giờ đã có

let a: Int? = Int("123")      // thành công, a là 123 (Optional)
let b: Int? = Int("abc")      // thất bại, b là nil

Rất nhiều hàm trong Swift trả về Optional khi thao tác có thể thất bại, như chuyển chuỗi thành số hay tìm phần tử trong mảng.

Cách 1: if let

Dùng khi chỉ muốn làm gì đó nếu có giá trị:

if let n = nickname {
    print("Biệt danh: \(n)")
} else {
    print("Chưa có biệt danh")
}

// Dạng rút gọn từ các bản Swift mới
if let nickname {
    print(nickname.uppercased())
}

Cách 2: guard let

Dùng để thoát sớm khi điều kiện không thỏa, giữ phần còn lại của hàm không bị lồng sâu:

func showProfile(name: String?, age: Int?) {
    guard let name = name, let age = age else {
        print("Thiếu thông tin")
        return
    }
    print("\(name), \(age) tuổi")
}

Biến được unwrap bằng guard còn dùng được trong toàn bộ phần sau của hàm.

Cách 3: toán tử nil-coalescing

Cung cấp giá trị mặc định khi nil:

let display = nickname ?? "Ẩn danh"
let count = Int(inputText) ?? 0

Cách 4: optional chaining

Gọi thuộc tính hoặc phương thức qua một chuỗi có thể nil; nếu bất kỳ mắt xích nào nil thì cả biểu thức trả về nil:

struct Address { var city: String }
struct User { var address: Address? }

let user = User(address: nil)
let city = user.address?.city   // nil, không gây lỗi
print(city ?? "Không rõ")

Dấu chấm than: force unwrap

Dấu ! ép mở hộp và gây lỗi dừng chương trình nếu bên trong là nil. Chỉ dùng khi bạn chắc chắn tuyệt đối giá trị tồn tại, và ngay cả khi đó, hầu hết trường hợp có cách an toàn hơn:

let value = Int("42")!   // chạy được nhưng nguy hiểm nếu chuỗi đầu vào thay đổi

// Cách an toàn hơn
guard let value = Int(text) else { return }

Implicitly unwrapped optional

Kiểu khai báo với ! như var label: UILabel! là optional tự mở hộp khi dùng. Bạn gặp nó nhiều ở các thuộc tính kết nối giao diện (IBOutlet) vì chúng được gán sau khi khởi tạo. Hãy hạn chế dùng cho code mới nếu có lựa chọn khác.

Các quy tắc ngắn gọn

  1. Mặc định hãy dùng kiểu không optional; chỉ dùng optional khi giá trị thật sự có thể không tồn tại.
  2. Ưu tiên if let, guard let và ?? thay vì !.
  3. Dùng guard let ở đầu hàm để xử lý đầu vào thiếu.
  4. Không biến mọi thứ thành optional chỉ để tránh phải khởi tạo.
  5. Dùng map hoặc flatMap trên Optional khi cần biến đổi giá trị bên trong gọn gàng.

Kết luận

Optional buộc bạn nghĩ tới trường hợp thiếu dữ liệu ngay lúc viết code thay vì để người dùng gặp sự cố lúc chạy. Khi đã quen với if let, guard let và toán tử ??, bạn sẽ thấy chúng giúp code rõ ràng và đáng tin cậy hơn.

Optional trong thực tế: ví dụ với dữ liệu JSON

Khi giải mã dữ liệu từ máy chủ, Optional xuất hiện rất tự nhiên vì một số trường có thể thiếu. Với Codable, bạn khai báo trường tùy chọn bằng dấu hỏi và Swift tự xử lý khi khóa vắng mặt:

struct Profile: Codable {
    let name: String
    let bio: String?      // có thể thiếu trong JSON
    let age: Int?
}

let json = #"{"name":"Lan"}"#.data(using: .utf8)!
let p = try JSONDecoder().decode(Profile.self, from: json)
print(p.name)
print(p.bio ?? "Chưa có giới thiệu")

Cách này tốt hơn nhiều so với việc dùng giá trị rỗng giả như chuỗi trống để thay cho "không có", vì kiểu dữ liệu nói rõ ý định. Khi hiển thị, kết hợp toán tử ?? hoặc if let để quyết định có vẽ phần giao diện đó hay không. Đây là mô hình bạn sẽ dùng hàng ngày khi làm ứng dụng iOS kết nối máy chủ, và hiểu nó vững sẽ tránh được phần lớn lỗi dừng đột ngột do unwrap sai.

Nếu muốn thực hành Swift qua các dự án thật, hãy tham khảo các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment