[Swift 2] Phân biệt “?” và “!”

4537
Như chúng ta đã biết Swift là ngôn ngữ mới, hiện đại và cũng không kém phần “hại não” cho những ai mới làm quen với ngôn ngữ này. Trong đó “?” và “!” chắc chắn là thứ mà làm nhiều anh em dev nhà ta bối rối. Bài viết này mình hy vọng sẽ giúp mọi người gỡ rối phần nào trong việc tìm hiểu “?” và “!” cũng như cách xài chúng ra sao.
Đầu tiên chúng ta thử xem xét đoạn mã sau:

Đoạn mã trên đại khái sẽ dùng navigation controller push màn hình tới 1 UIViewController nào đó (someViewController), đây là cách chúng ta vẫn thường làm. Thế nhưng lỡ self.navigationController bị nil thì sao ?? Rõ ràng nếu trong trường hợp ở UIViewController mà chúng ta gọi đoạn code trên mà nó không có navigation controller thì app sẽ bị crash.

Ta có thể hoàn toàn xử lý đoạn mã trên bằng cách thêm 1 đoạn check xem self.navigationController có đang là nil hay không để xử lý lỗi này. Nhưng Swift với tiêu chí giúp cho code chúng ta an toàn hơn đã giới thiệu cơ chế optional (?). Từ đó ta sẽ có đoạn mã sau:

Nếu quan sát thì đoạn mã này chỉ khác với đoạn mã đầu tiên là thêm vào 1 dấu “?”. Và đây cũng là điều bắt buộc trong Swift, nghĩa là về mặt thực tế đoạn mã đầu tiên sẽ không thể build được và XCode sẽ gợi ý cho ta chèn thêm “?” vào. Bởi vì thuộc tính navigationController trong UIViewController được khai báo như sau:

 

Vậy tóm lại “?” có nghĩa là gì:

  1. Trong khai báo biến, “?” có nghĩa là ta nói rằng biến đó có khả năng bị nil chứ không phải lúc nào cũng có giá trị (hoặc con trỏ gán vào). Trường hợp ở trên nếu UIViewController chạy độc lập thì biến navigationController của nó sẽ là nil.
  2. Trong câu lệnh thông thường, dấu “?” xuất hiện báo hiệu rằng nếu biến đó đang là nil thì toàn bộ những gì sau “?” sẽ không được thực thi, app sẽ không crash.
  3. *** “?” hoạt động như 1 màng mana shield (lá chắn phép trong game :D) bảo vệ cái biến đó. Vì thế sẽ có khái niệm wrapping và unwrapping mà khi tới “!” ta sẽ hiểu hơn.
Từ đó “?” trong các câu lệnh sau sẽ:

 

Khi nào ta dùng “!”

Về cơ bản ta dùng “!” khi cực kỳ chắc chắn rằng biến có “!” sẽ luôn luôn có giá trị. Biến có “!” trên thật tế ta có thể hiểu nó là biến optional nhưng luôn được unwrap tự động mỗi khi ta dùng nó mà không cần phải thêm “?” phía sau nữa. Cơ chế này được biết đến với tên: Implicit Unwrap Optional. Như vậy rõ ràng có những biến trong app sẽ luôn có giá trị khởi tạo và không thay đổi xuyên suốt app thì ta có thể dùng “!” cho đỡ mắc công unwrap nó, cũng như việc check nó xem có nil hay là không.

** Theo kinh nghiệm cá nhân của mình: nếu biến được khai báo với từ khóa “let” và có khởi tạo giá trị ngay thì ta có thể dùng “!” cho biến đó. Tương tự cho thuộc tính của một class mà trong hàm dựng nó luôn được gán vào 1 giá trị khác nil.

Lúc này ta chỉ còn gặp phiền hà một chút vì thi thoảng XCode lại báo ta nên chèn “!” vào ngay sau biến tham số (nếu biến đó là “?”) khi ta gọi 1 hàm nào đó. Tại sao vậy nhỉ ???? Đoạn code sau đây sẽ làm sáng tỏ vấn đề:

Như vậy khi ta đang code ngon lành mà XCode nhắc mình thêm “!” nghĩa là các bạn đang gọi tới func nào đó mà iOS thiết kế cho tham số của nó không được phép nil. Và đây cũng là cách mà ta quyết định cho tham số cho hàm có thể được phép nil hay không.

Hy vọng qua bài viết này mình đã giúp các bạn phần nào hiểu hơn về “?” và “!” trong Swift nhé 🙂

Viet Tran – Director at IDE Academy

CHIA SẺ