Bài này được dịch từ đây: alisoftware.github.io

Bài này là 1 phần của series. Bạn có thể đọc các phần còn lại ở đây: phần 1, phần 1 bổ sung, phần 2, phần 3, phần 4

Đừng bao giờ giết một pony ?

Trong bài viết lần trước, tôi kêu gọi các bạn không sử dụng !. Một số bạn có thể đã hiểu theo kiểu tiêu cực như là “không bao giờ sử dụng nó, đừng bao giờ”. Những gì tôi nói là trong thực tế “mỗi khi bạn thêm một ! chỉ vì trình biên dịch gợi ý, bạn đang giết chết một pony 🐴 “. Nhưng chắc chắn rằng 🐴 có thể tiếp tục sống nếu bạn thực sự biết những gì bạn đang làm. Đừng làm điều đó chỉ vì trình biên dịch đề nghị, hãy suy nghĩ thật kỹ.

Trong một số trường hợp, sử dụng implicitly-unwrapped optionals vẫn có ích. Nhưng chỉ khi nào bạn nghĩ kỹ về nó, bạn biết rõ lý do tại sao bạn sử dụng nó và nó sẽ an toàn.

Khi nào thì từ bỏ ponies?

Dưới đây là một vài trường hợp mà bạn sử dụng ! sẽ an toàn trong Swift. Có lẽ, không chỉ các trường hợp dưới đây sử dụng ! mà còn nhiều trường hợp khác, nhưng đây là các trường hợp thường xuyên hay được sử dụng mà tôi có thể nghĩ ra.

1. IBOutlets + Dependency Injection

IBOutlets là một trường hợp đặc biệt, nó có thể nil ở phần cuối của init method (bởi vì nó không thể được khởi tạo quá sớm), nhưng nó sẽ có value một cách nhanh chóng sau khi instance khởi tạo xong (hoặc bằng cách Dependency Injection hoặc thông qua cơ chế XIB-loading). Vì vậy, ngay cả khi nó là optional(nó đã không được khởi tạo trong suốt quá trình init, mà chỉ là một khoảng khắc ngắn ngủi sau đó), bạn chắc chắn rằng, theo thiết kế, nó sẽ không bao giờ nil trong phần còn lại của code . Đó là một trường hợp mà implicitly-unwrapped có ích, vì bạn biết nó sẽ không bao giờ nil trong suốt quá trình sử dụng nó.

2. UIImage, UIStoryboard, UITableViewCell

Tất cả các method dưới đây được khởi tạo sử dụng names và identifiers là hằng số:

swift
1
2
3
4
5
UIImage(named: …)
UIStoryboard(name:,bundle:)
UIStoryboard.instantiateViewControllerWithIdentifier(_:)
UITableView.dequeueReusableCellWithIdentifier(_:, forIndexPath:)
// and some other similar stuff…

Đối với những trường hợp sử dụng, bạn có thể muốn mã của bạn để sụp đổ nếu bạn viết sai name/indentifier, bởi vì nó sẽ là một lỗi phát triển (nguyên nhân là thiếu image trong bundle hoặc storyboard bị failed) , và có thể bạn muốn phát hiện sớm lỗi ở giai đoạn phát triển để sửa chữa nó càng sớm càng tốt.

Lưu ý rằng đối với những trường hợp, bạn cũng có thể thích sử dụng guard let else fatalError() pattern, để cung cấp message error chi tiết hơn trong trường hợp phát sinh lỗi:

swift
1
2
3
4
guard let cell = tableView.dequeueReusableCellWithIdentifier("foo", forIndexPath:indexPath) as? MyCustomCell else {
  fatalError("cell with identifier 'foo' and class 'MyCustomCell' not found. "
    + "Check that your XIB/Storyboard is configured properly.")
}

Đó cũng là lý do tại sao bạn sẽ muốn sử dụng thủ thuật như những gì tôi đã thảo luận trong enums as constants và sử dụng SwiftGen để tránh những khả năng bị lỗi chính tả nhận dạng và bị treo 😉.

Ví dụ: SwiftGen sử dụng UIImage(named: asset.rawValue)! trong việc thực hiện của nó, bởi vì các enum mà bạn sử dụng được tạo ra bởi công cụ SwiftGen, và nó đảm bảo hình ảnh có tên đó luôn tồn tại trong Assets Catalog - vì vậy bằng cách thiết kế này, nó không thể là nil.

Tôi có nên từ bỏ ponies vào những trường hợp đặc biệt không?

Phần đầu tiên của series bài này hướng nhiều đến đối tượng là những người-mới-tìm-hiểu Swift, vì họ hay sử dụng force-unwrap bất cứ lúc nào chỉ vì Xcode gợi ý cho họ, hoặc vì họ không thực sự hiểu rõ tại sao Optionals là tốt cho họ. Đó là lí do tại sao tôi không nói về những chủ đề nâng cao hơn mà tôi đang hướng đến.

Vì vậy, có những trường hợp sử dụng ! là hợp lý. Nhưng, lời khuyên của tôi trong phần 1 vẫn còn nguyên: chỉ sử dụng ! nếu bạn thực sự hiểu tại sao bạn sử dụng nó và bạn nghĩ về nó trước tiên, không làm điều đó chỉ vì trình biên dịch gợi ý. Đặc biệt, nếu bạn là người-mới-tìm-hiểu Swift và bạn muốn thêm ! chỉ vì “optionals rất khó chịu với các lỗi của nó, tôi muốn trình biên dịch ngừng phàn nàn”, bạn đang làm sai và đó là nơi mà bạn bắt đầu giết ponies.