Swift IF LET được đánh giá như thế nào?


86

Tôi đã thấy mã này trên trang Swift và các bài đăng khác nhau ở đây và tôi đang cố gắng nắm bắt những điều cơ bản. Dòng này được đánh giá như thế nào?

if let name = optionalName {

Tôi bối rối vì nó không phải tên == tên tùy chọn, nó chỉ định giá trị, vậy làm thế nào để báo cáo đó đúng và tại sao nó không đúng khi bạn thay thế bằng john appleeed bằng nil, vì nó vẫn sẽ bằng nhau?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

10
Tra cứu "ràng buộc tùy chọn" trong tài liệu Swift ...
Martin R

3
Xem chi tiết các tùy chọn tại dev.iachieved.it/iachievedit/?p=314 , if letcú pháp được gọi là ràng buộc tùy chọn.
Joe

Câu trả lời:


100

Về cơ bản, dòng nói, "nếu bạn có thể để biến mới namebằng phiên bản không tùy chọn của optionalName, hãy làm như sau với nó". Như Martin đã chỉ ra, điều này được gọi là Ràng buộc không bắt buộc .

Mục đích duy nhất của nó là để kiểm tra xem một biến tùy chọn có chứa giá trị thực hay không và liên kết biểu mẫu không tùy chọn với một biến tạm thời. Đây là cách an toàn để "mở" một tùy chọn hay nói cách khác, truy cập vào giá trị có trong tùy chọn. Nó không phải là thử nghiệm cho sự bình đẳng dưới bất kỳ hình thức nào. Nó chỉ đang kiểm tra sự tồn tại của một giá trị trong một tùy chọn.


1
Tôi sẽ đọc nó khi tôi tìm hiểu nó, tôi chỉ bắt đầu phần giới thiệu nhanh và nó không giải thích nó. bạn giải thích có ý nghĩa hoàn hảo, Cảm ơn.
DeadZero

1
Tại sao chúng ta không nên sử dụng "! =" Thay vì "if let" để kiểm tra xem biến tùy chọn có giá trị như - if
optionName

4
@Nuibb vì khi sử dụng, if letchúng tôi liên kết giá trị với một biến không tùy chọn ( nametrong ví dụ này). Ví dụ của bạn sẽ không biên dịch vì bây giờ không có biến nào được gọi name. Nếu bạn thay đổi ví dụ của mình để sử dụng, optionalNamenó sẽ in ra dưới dạng Hello, Optional("John Appleseed"). Bạn có thể sử dụng chức năng mở gói cưỡng bức sau khi kiểm tra chống lại nil Hello, \(optionalName!)nhưng điều này chỉ dễ xảy ra lỗi hơn nếu bạn di chuyển đoạn mã đó đến một nơi nào đó mà không kiểm tra.
drawag

29

Một tùy chọn là đặt hoặc không đặt (not nil hoặc nil) ... để lại cho chúng tôi một quyết định quan trọng. "Chúng ta nên viết mã của mình như thế nào để nó có thể hoạt động chính xác cho cả 2 trạng thái?". Cách chúng tôi unwrap các tùy chọn là những gì quyết định rằng đối với chúng tôi.

Có một số cách tiếp cận mà bạn có thể sử dụng để chống lại một tùy chọn không được thiết lập.

  • Tai nạn!
  • Mặc định giá trị thành một cái gì đó - nếu nó chưa được đặt.
  • Không thành công một cách duyên dáng tức là không làm gì cả, nhưng cũng nếu giá trị đã được đặt, thì hãy gán nó.
  • Thất bại một cách duyên dáng tức là không làm gì cả, tuy nhiên nếu giá trị đã được đặt ... hãy làm gì đó (nó chỉ hơn một nhiệm vụ duy nhất).

Dưới đây là 4 cách tiếp cận


Việc sử dụng bắt buộc mở gói sẽ bị lỗi nếu bạn không có giá trị. Bạn sẽ muốn làm điều này nếu có giá trị đó là quan trọng hàng đầu, ví dụ như tiêu đề của một bộ phim (mọi bộ phim PHẢI có tên). !được sử dụng để mở gói cưỡng bức.

movieTitle = movie.title!

Sử dụng liên kết nil là một cách khác sẽ cung cấp cho bạn nhiều quyền kiểm soát hơn , có nghĩa là nó sẽ không sụp đổ nếu giá trị không được đặt, cũng như 'không đặt nó không có gì' nếu nó không được đặt ... nó sẽ làm những gì bạn nói với nó để làm ví dụ, nó sẽ mặc định / đặt tên phim thành unsitled_movie nếu không có tên nào được đặt. ??được sử dụng cho liên kết nil.

var movieTitle = movie.title ?? "untitled_Movie"

Sử dụng Chuỗi tùy chọn sẽ không làm gì nếu bạn không có giá trị và sẽ đặt giá trị nếu bạn có giá trị. Bạn làm điều này cho một cái gì đó mà việc đặt giá trị của nó không có tầm quan trọng quan trọng, ví dụ như tên của đại lý của diễn viên của bạn . ?được sử dụng cho chuỗi tùy chọn.

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

Việc sử dụng if-let(hoặc guardlà hai loại ràng buộc tùy chọn khác nhau ) sẽ cung cấp cho bạn nhiều quyền kiểm soát hơn , nó sẽ không bị lỗi nếu giá trị không được đặt. Nếu giá trị được đặt, thì bạn có thể làm gì đó. Nếu nó chưa được đặt thì bạn có thể thêm một elsecâu lệnh.

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

Đây là cách mở gói được sử dụng phổ biến nhất, vì việc mở gói cưỡng bức hơi không được khuyến khích. Để biết thêm thảo luận về lý do tại sao nó không được khuyến khích, hãy xem tại đây . Để có sự so sánh tốt giữa guardif-letxemguard vs. if-let


Lưu ý phụ:

Ràng buộc tùy chọn và chuỗi tùy chọn thường được sử dụng cùng nhau:

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 

Tại sao việc mở gói cưỡng bức lại không được khuyến khích trong tình huống phimTitle không bao giờ có thể là bất kỳ thứ gì khác ngoài một chuỗi và tất cả các chuỗi đều hợp lệ cho movieTitle? (và tôi không muốn "bộ phim chưa có tiêu đề" Tôi muốn "") Buộc mở gói là cách thích hợp duy nhất cho tình huống này, sẽ thật tuyệt nếu bạn có thể xóa phần có nội dung "buộc phải mở gói hơi không được khuyến khích" vì đó là thông tin sai .
Andy

Giả sử bạn thực hiện một cuộc gọi mạng và một số nhà phát triển của nhóm máy chủ đã đưa ra quyết định tồi và quên gửi tiêu đề phim. Bạn có muốn ứng dụng của mình gặp sự cố trong quá trình sản xuất không? Hay chỉ viết tiêu đề không rõ? Thực tế là một số phim trên IMDb không có tiêu đề :). Ngoài ra, buộc mở ra ngụ ý rằng bạn chưa thực hiện bất kỳ ghi nhật ký hoặc xác nhận nào. Điều đó thật xấu. Bởi vì bạn sẽ không biết nguyên nhân gốc rễ là gì.
Honey

Đó là một lập luận của người đàn ông rơm, tôi chưa bao giờ nói "luôn luôn sử dụng cách mở gói cưỡng bức." Chỉ vì bạn không nên sử dụng việc mở gói cưỡng bức trong ví dụ của mình không có nghĩa là việc mở gói cưỡng bức không được khuyến khích ở mọi ví dụ. Tôi đã đưa cho bạn một kịch bản trong đó buộc mở gói là giải pháp đúng đắn duy nhất trong số bốn giải pháp bạn đã trình bày. Bạn có thể cung cấp một giải pháp tốt hơn cho tình huống đã nêu nhận xét trước đây của tôi không? Nếu không, vui lòng xem xét sửa đổi nhận xét của bạn về việc "buộc mở gói có phần không được khuyến khích" bởi vì nó không có phần nản nếu không xem xét bối cảnh.
Andy

Nếu bạn đang mặc định điều gì đó là “” thì đó không còn là tùy chọn nữa
Honey

Ví dụ: giá trị "" đó đến từ thuộc tính văn bản của một phiên bản UILabel được tạo trong bảng phân cảnh, đó là tùy chọn vì nó có thể là 0 nếu bạn tạo động, nhưng ở đây bạn không tạo động nên nó sẽ luôn chứa giá trị chuỗi . Bạn sẽ không sử dụng việc mở gói bắt buộc trong trường hợp này, thay vào đó, bạn sẽ mở gói bằng if-let và cung cấp một giá trị giống với giá trị mặc định của nó ""? Bạn có thể, nhưng điều đó vô nghĩa, không cần thiết và dài dòng. Và điều gì sẽ xảy ra nếu bạn đang sử dụng một thư viện HTTP sẽ luôn trả về một từ điển ngay cả khi nó bị lỗi. Nó phụ thuộc vào ngữ cảnh.
Andy

4

Cú pháp if chấp nhận 2 điều kiện khác nhau. Thứ hai, một ràng buộc tùy chọn, không phải là một boolean. Điều này thật khó hiểu, như bạn có thể viết:

if let name = optionalName {

nhưng không

if (let name = optionalName) {

Tài liệu của Apple (tham chiếu Swift):

Giá trị của điều kiện phải là kiểu Boolhoặc kiểu được bắc cầu Bool. Điều kiện cũng có thể là một khai báo ràng buộc tùy chọn, như đã thảo luận trong Ràng buộc tùy chọn .


3

if chỉ nhận các biểu thức boolean, ngoài ra nó sẽ gây ra lỗi, vì vậy đoạn mã này nói rằng

if let name = optionalName {

}else{

}

nếu optionName là nil thì điều kiện là false và câu lệnh else sẽ thực thi. Tuy nhiên, nếu tùy chọnName có một số giá trị thì giá trị tùy chọn được mở / gán vào biến hằng tức là tên.


1

Bất cứ khi nào bạn đang làm việc với các tham chiếu yếu, các loại tùy chọn sẽ tốt hơn nếu sử dụng nếu cho phép để bảo vệ mã của bạn an toàn và tránh sự cố. Đây là các ví dụ

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.