Toàn tập về Optional trong Swift
Bài viết giải thích chi tiết về kiểu Optional trong Swift, từ lý do cần có Optional, cách sử dụng các kỹ thuật như Forced Unwrapping, Optional Binding, Implicitly Unwrapped Optionals, Nil coalescing và Optional Chaining, kèm theo các ví dụ code cụ thể để giúp lập trình viên iOS hiểu và áp dụng đúng cách.

Giới thiệu
Trước khi mình học Swift thì có học qua C++, C#, Ruby, Python, những ngôn ngữ này đều không có kiểu Optional, hoặc có nhưng khó dùng ( hiện giờ C++, C# cũng có optional ). Mình cũng phải mất khoảng thời gian mới hiểu rõ Optional trong Swift. Bạn có tự hỏi khi nào nên xài !, khi nào xài ?, và tại sao có 2 dấu này trong Swift. Rồi mấy thuật ngữ như Forced Unwrapping, Optional Binding, Nil coalescing là cái khỉ gì? Khi vọng bài viết này sẽ giúp bạn hiểu rõ về kiểu Optional này cũng như những thắc mắc trên.
Tại sao cần có kiểu Optional
Trước khi tìm hiểu những khái niệm như Forced Unwrapping, Optional Binding, Implicitly Unwrapped Optionals, Nil coalescing, Optional Chaining là gì. Chúng ta cần hiểu được tại sao cần có Optional.
Một trong những lỗi thường gặp nhất của lập trình viên là lỗi dùng một biến nhưng biến đó bị nil ( null ).
Lúc mình học thì cứ nghĩ: "Ừ, biến mình khởi tạo mà, mắc mớ gì nó bị nil mà mình không biết". Vậy nguyên nhân do đâu? Thực tế thì đâu là những trường hợp mà một biến dễ bị nil nhất:
-
Do user, ví dụ bắt user nhập username và password nhưng họ lại để trống rồi nhấn nút Login luôn. Nếu dev không check xem user có nhập đúng không sẽ bị lỗi.
-
Đổi kiểu dữ liệu. Ví dụ nút cần tính tổng tiền cho user nhưng control textfield trả về giá trị luôn luôn là kiểu string, nếu user nhập không phải là số mà dev không check và lấy giá trị sai này convert sang double luôn thì biến cũng nil.
-
Do lấy dữ liệu từ server. Ví dụ bạn parse JSON từ API, nhưng ông backend lại không trả về dữ liệu cho bạn mà bạn không check lại thì cũng teo.
Khi phát triển ứng dụng thì sẽ có rất nhiều trường hợp khác sẽ dẫn đến biến bị nil, nhưng trên đây là 3 trường hợp hay bị nhất. Đó là lý do có kiểu Optional trong Swift. Các bạn cũng đừng thần thánh quá Swift, vì kiểu Optional trong Swift cũng mượn ý tưởng từ các ngôn ngữ trước như Rust.
Kiểu Optional
Optional cũng như bao kiểu dữ liệu khác trong Swift. Chẳng hạn ta có UIImage và UIImage?. Chúng là 2 kiểu dữ liệu khác nhau. Khi bạn khai báo một biến kiểu UIImage, thì bạn đang nói với complier là "biến kiểu UIImage này của tao chắc chắn sẽ có giá trị, đừng lo". Ví vụ bạn có một biến là appLogo để lưu cái hình logo của app, và bạn gán cho nó một hình luôn.
Còn khi bạn khai báo biến kiểu UIImage?, thì bạn đang nói với complier là "biến này của tao là kiểu UIImage , có thể nó sẽ bị nil đó, khi tao xài biến này nhớ nhắc tao nha". Ví dụ bạn đang làm một app mạng xã hội giống Facebook, bạn đang parse các status từ API. Mà một status thì sẽ có thể có caption hoặc hình hoặc video.
struct Status {
var statusId: Int
var createdAt: String
var userId: Int
var caption: String?
var image: UIImage?
var videoUrl: String?
}
Vì caption, hình và videoUrl có thể nil nên bạn khai báo kiểu Option cho chúng.
Thực chất, Optional là một enum
enum Optional<T> {
case None
case Some(T)
}
Do đó, bạn có thể khai báo biến kiểu Optional như vậy cũng được, nhưng thưc tế ít ai dùng cách thứ 2 lắm
// Hai dòng code này như nhau
let x: String? = nil
let x = Optional.none
// Hai dòng code này như nhau
let y: String? = "Hi there"
let y = Optional.some("Hi there")
Forced Unwrapping
Khi bạn khai báo một biến kiểu Optional và bạn dùng nó, complier sẽ thông báo và nhắc cho bạn biết là "mày đang dùng kiểu Optional kìa"
Khi bạn thêm dấu ! vào sau một biến kiểu Optional thì bạn đang nói với complier là: "Vô tư đi, không sao đâu, tui biết chắc chắc biến đó có giá trị mà, không nil đâu mà sợ"
Nhưng để an tâm, bạn có thể check xem biến yearOfBirth có giá trị không rồi thêm ! ( forced unwrapping ) cũng được:
var yearOfBirth: Int?
if yearOfBirth != nil {
var age = 2018 - yearOfBirth!
}
Mà tại sao lại gọi là forced unwrapping. Bạn cứ tưởng tượng giá trị của biến kiểu Optional đang được bỏ trong một cái hộp ( box ). Bạn muốn lấy phải mở hộp ra ( unwrapping ). Bên trong hộp có thể có giá trị hoặc không.
Optional Binding
Cũng như forced unwrapping, Optional Binding cũng là một cách để "mở hộp"
var yearOfBirth: Int?
if let yearOfBirth = yearOfBirth {
var age = 2018 - yearOfBirth
print("Tuoi cua ban \(age)")
} else {
print("yearOfBirth is nil")
}
Bạn chú ý đến keyword là if let. Tức là "nếu có".
Nếu biến yearOfBirth có giá trị thì gán giá trị đó cho hằng yearOfBirth ( bạn có thể dùng biến bằng cách đổi if let thành if var hoặc tên biến/hằng khác cũng được, mình dùng if let vì không thay đổi giá trị của yearOfBirth ). Hằng yearOfBirth này chỉ dùng được trong scope if. Ngược lại nếu biến yearOfBirth không có giá trị thì thưc hiện code trong scope else.
Implicitly Unwrapped Optionals
Với một biến kiểu Optional, muốn dùng nó ta phải forced unwrapping ( hoặc optional binding ). Ví dụ dùng ở 4 chỗ thì phải forced unwrapping 4 lần. Implicitly Unwrapped Optionals tức là forced unwrapping ngay lúc khởi tạo biến đó luôn.
Xem ví dụ sau để rõ hơn nhé:
Bình thường nếu tạo một UIImage từ một file name thì sẽ trả về kiểu UIImage?
Bởi vì khi lập trình bạn có thể gõ sai tên file hoặc thằng trong team nó đổi tên khác thì app sẽ crash.
Nhưng nếu bạn chắc chắn 100% tên file đúng thì thêm ! ngay lúc khai báo như sau
let appLogo: UIImage = UIImage(named: "girl")!
Như thế gọi là Implicitly Unwrapped Optionals. Sau này dùng hằng appLogo thì không cần forced unwrapping ( hoặc optional binding ) gì nữa hết.
Nil coalescing
Đây là cách để phòng hờ lỗi khi dùng biến kiểu Optional. Cách dùng như sau **** **?? **
var yearOfBirth: Int?
print("yearOfBirth is \(yearOfBirth ?? 21)")
Nếu yearOfBirth bị nil thì dùng giá trị 21, không thì dùng giá trị đã unwrapped của yearOfBirth
Optional Chaining
Định nghĩa từ Apple như sau:
Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be
nil
. If the optional contains a value, the property, method, or subscript call succeeds; if the optional isnil
, the property, method, or subscript call returnsnil
. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain isnil
.
Tóm lại là hơi khó hiểu, mình sẽ lấy một ví dụ sau:
class Person {
var bankAccount: BankAccount?
}
class BankAccount {
var balance: Int?
}
Một tài khoản ngân hàng thì có thể không có balance ( không đúng tự nhiên nhưng kệ :D )
Một người thì có thể có tài khoản ngân hàng hoặc khôngkhông
var person = Person()
if let bankAccount = person.bankAccount {
if let balance = bankAccount.balance {
print("balance = \(balance)")
} else {
print("không có balance")
}
} else {
print("không có bankAccount")
}
Nếu từ từ dùng Optional binding như trên thì bạn sẽ biết được do không có tài khoản ngân hàng hay không có balance.
Nhưng nếu mục đích của bạn chỉ là cần biết balance là bao nhiêu thôi thì dùng như sau:
if let balance = person.bankAccount?.balance {
print(balance)
} else {
print("Có thể không có bankAccount hoặc không có balance")
}
Đây được gọi là Optional Chaining. Trong quá trình lấy balance, nếu bankAccount = nil hoặc balance = nil thì đều rơi vào scope else
Tức là nếu bạn có chain 100 cái optional cũng được, vẫn lấy được giá trị cuối của chuỗi ( optional chain ) đó, nhưng cái nào bị nil thì bạn không biết.
Kết
Hy vọng với bài viết khá đầy đủ này, bạn sẽ không còn lúng túng khi dùng ! hay ? trong Swift nữa.
Bạn cũng không cần nhớ tên kĩ thuật nó là Forced unwrapped, Optional Binding, Implicitly Unwrapped Optionals, Nil coalescing, Optional Chaining gì đâu. Nhớ thì tốt, không nhớ cũng chẳng sao, quan trọng là bạn hiểu.
Ở bài sau, chúng ta sẽ so sánh khi nào nên dùng if let và guard let nhé.
Bài viết cũng là tài liệu tham khảo thêm trong khóa học iOS với Swift.
Xem thêm các bài viết khác:
https://niviki.com/lo-trinh-hoc-swift-va-ios-co-ban-den-nang-cao/
https://niviki.com/quan-ly-bo-nho-trong-swift/
Related Posts
Discover more content you might enjoy

Game Theory trong thời đại AI: Khi máy móc tham gia vào "trò chơi"
Bài viết phân tích sự giao thoa giữa lý thuyết trò chơi (Game Theory) và trí tuệ nhân tạo, giải thích cách AI đang thay đổi các nguyên lý cân bằng Nash và chiến lược tối ưu. Tác giả đưa ra các ví dụ thực tế về ứng dụng trong kinh doanh, giao thông và an ninh mạng.

Bài này không phải AI viết
Suy ngẫm chân thành về giá trị của việc viết thủ công trong kỷ nguyên AI. Dù AI có thể tạo nội dung hiệu quả, bài viết này là lời khẳng định về sự kết nối cá nhân và giá trị độc đáo mà con người mang lại cho văn bản của mình.

Dự đoán về Vibe Coding: Cách AI sẽ biến đổi việc tạo ra phần mềm
Bài viết phân tích cách 'vibe coding' - phương pháp lập trình dựa trên mô tả ý định thay vì viết code trực tiếp - sẽ dân chủ hóa việc phát triển phần mềm. Tác giả dự đoán về sự chuyển đổi từ giao diện dòng lệnh sang thiết kế trực quan, sự xuất hiện của phần mềm tự cải thiện, và tác động đến cấu trúc tổ chức công ty cũng như các thị trường ngách chưa được khai thác.

Dùng AI để hỗ trợ đầu tư crypto
Bài viết chia sẻ 7 mẹo thực tế để sử dụng AI (như Claude.ai và ChatGPT) hỗ trợ hiểu rõ whitepaper và tài liệu kỹ thuật của các dự án blockchain. Từ việc yêu cầu tóm tắt đơn giản, giải thích như cho trẻ em, đặt câu hỏi làm rõ, sử dụng ví dụ, tạo tình huống giả định, chuyển đổi thuật ngữ, đến so sánh nhiều nguồn tài liệu - giúp nhà đầu tư đưa ra quyết định đầu tư crypto sáng suốt hơn.

Time.delta là gì?
Tìm hiểu về Time.delta trong Unity và cách sử dụng Time.deltaTime để tạo chuyển động mượt mà trong game

Bức xức không làm ta vô can & Điểm đến cuộc đời
Đánh giá hai tác phẩm của Đặng Hoàng Giang với góc nhìn phản biện về những vấn đề xã hội nóng hổi. Bài viết phân tích cách tác giả sử dụng văn phong châm biếm, mỉa mai để thúc đẩy tư duy phản biện, đồng thời chia sẻ những suy ngẫm cá nhân về giá trị của hai cuốn sách này.