Sử dụng Swift if let với toán tử AND logic &&


93

Chúng tôi biết rằng chúng tôi có thể sử dụng một if letcâu lệnh như một tốc ký để kiểm tra một nil tùy chọn sau đó mở ra.

Tuy nhiên, tôi muốn kết hợp điều đó với một biểu thức khác bằng cách sử dụng toán tử logic AND &&.

Vì vậy, ví dụ, ở đây tôi thực hiện chuỗi tùy chọn để mở và tùy chọn downcast rootViewController của tôi xuống tabBarController. Nhưng thay vì có các câu lệnh if lồng nhau, tôi muốn kết hợp chúng.

if let tabBarController = window!.rootViewController as? UITabBarController {
    if tabBarController.viewControllers.count > 0 {
        println("do stuff")
     }
 }

Cho kết hợp:

if let tabBarController = window!.rootViewController as? UITabBarController &&
    tabBarController.viewControllers.count > 0 {
        println("do stuff")
     }
}

Ở trên đưa ra lỗi biên dịch Sử dụng mã định danh chưa được giải quyết 'tabBarController'

Đơn giản hóa:

if let tabBarController = window!.rootViewController as? UITabBarController && true {
   println("do stuff")
}

Điều này gây ra lỗi biên dịch Giá trị ràng buộc trong ràng buộc có điều kiện phải thuộc loại Tùy chọn . Đã thử các biến thể cú pháp khác nhau, mỗi biến thể đều cho một lỗi trình biên dịch khác nhau. Tôi vẫn chưa tìm thấy sự kết hợp chiến thắng của thứ tự và dấu ngoặc đơn.

Vì vậy, câu hỏi là, nó có thể và nếu vậy thì cú pháp chính xác là gì?

Lưu ý rằng tôi muốn thực hiện điều này với một ifcâu lệnh không phải một switchcâu lệnh hoặc một toán ?tử bậc ba .


Việc cung cấp các thông báo lỗi trong câu hỏi luôn là một ý kiến ​​hay.
zaph

Tuyên bố đơn giản hơn cho những người thích thử nghiệm điều này:var foo : Int? = 10; if let bar = foo { if bar == 10 { println("Great success!") }}
DarkDust

Thông báo lỗi khi sử dụng if let bar = foo && bar == 10Use of unresolved identifier "bar"( bartất nhiên là trên thứ hai ).
DarkDust

chỉ cần lưu ý rằng tôi đã có thể rút ngắn ví dụ trên bằng cách sử dụng firstObject của Objective C như sau: if let navigationController = tabBarController.viewControllers.bridgeToObjectiveC (). firstObject as? UINavigationController {
Max MacLeod

1
1. bridgeToObjectiveCđã ra mắt trong bản beta 5 (và có thể không bao giờ dành cho mục đích sử dụng chung). 2. Dù sao cũng có một firstphương thức trên kiểu tích hợp của Swift Array.
rickster

Câu trả lời:


143

Kể từ Swift 1.2, điều này hiện có thể . Các Swift 1.2 và Xcode 6.3 beta release notes nhà nước:

Mở gói tùy chọn mạnh mẽ hơn với if let - Cấu trúc if let hiện có thể mở nhiều tùy chọn cùng một lúc, cũng như bao gồm các điều kiện boolean can thiệp. Điều này cho phép bạn thể hiện luồng điều khiển có điều kiện mà không cần lồng ghép không cần thiết.

Với câu lệnh trên, cú pháp sau đó sẽ là:

if let tabBarController = window!.rootViewController as? UITabBarController where tabBarController.viewControllers.count > 0 {
        println("do stuff")
}

Điều này sử dụng wheremệnh đề.

Một ví dụ khác, lần này truyền AnyObjectđến Int, mở gói tùy chọn và kiểm tra xem tùy chọn chưa gói có đáp ứng điều kiện:

if let w = width as? Int where w < 500
{
    println("success!")
}

Đối với những người hiện đang sử dụng Swift 3, "where" đã được thay thế bằng dấu phẩy. Do đó, tương đương sẽ là:

if let w = width as? Int, w < 500
{
    println("success!")
}

2
Đây sẽ là câu trả lời được chọn.
Francis.Beauchamp

có như bây giờ nó đã thay đổi. Câu trả lời của Bryan là đúng vào thời điểm đó
Max MacLeod.

58

Trong ví dụ của Swift 3 Max MacLeod sẽ như thế này:

if let tabBarController = window!.rootViewController as? UITabBarController, tabBarController.viewControllers.count > 0 {
    println("do stuff")
}

Đã wheređược thay thế bởi,


10
Vì vậy, dành cho && là gì ở đó cho || ?
jeet.chanchawat

9
@ jeet.chanchawat logic HOẶC không có ý nghĩa trong ngữ cảnh này. if letchỉ có thể tiếp tục nếu tùy chọn được mở thành công và được gán cho tên biến mới. Nếu bạn đã nói OR <something else>thì bạn có thể dễ dàng bỏ qua toàn bộ mục đích của if let. Đối với HOẶC logic, chỉ cần thực hiện bình thường ifvà bên trong phần thân xử lý thực tế là đối tượng đầu tiên vẫn là tùy chọn tại điểm đó (không phải là không được bao bọc).
jhabbott

37

Câu trả lời của Max là đúng và một cách để làm điều này. Lưu ý rằng khi viết theo cách này:

if let a = someOptional where someBool { }

Các someOptionalbiểu hiện sẽ được giải quyết đầu tiên. Nếu nó không thành công thì someBoolbiểu thức sẽ không được đánh giá (đánh giá ngắn mạch, như bạn mong đợi).

Nếu bạn muốn viết điều này theo cách khác, nó có thể được thực hiện như vậy:

if someBool, let a = someOptional { }

Trong trường hợp someBoolnày được đánh giá đầu tiên và chỉ khi nó được đánh giá là true thì someOptionalbiểu thức mới được đánh giá.


5

Swift 4 , tôi sẽ sử dụng,

let i = navigationController?.viewControllers.index(of: self)
if let index = i, index > 0, let parent = navigationController?.viewControllers[index-1] {
    // access parent
}

4

Điều đó là không thể.

Từ ngữ pháp Swift

GRAMMAR CỦA MỘT BÁO CÁO NẾU

if-statement → if if-condition code-block else-clauseopt

if-condition → biểu thức | tờ khai

mệnh đề khác → khối mã else | khác nếu-tuyên bố

Giá trị của bất kỳ điều kiện nào trong câu lệnh if phải có kiểu phù hợp với giao thức BooleanType. Đ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

if-condition phải là biểu thức hoặc khai báo. Bạn không thể có cả biểu thức và khai báo.

let foo = barlà một khai báo, nó không đánh giá đến một giá trị phù hợp BooleanType. Nó khai báo một hằng / biến foo.

Giải pháp ban đầu của bạn đủ tốt, nó dễ đọc hơn nhiều sau đó kết hợp các điều kiện.


nhưng chắc chắn "if let" - cú pháp Swift hợp lệ - vừa là một biểu thức vừa là một khai báo?
Max MacLeod

@MaxMacLeod let foo = barlà khai báo không phải là biểu thức. bạn không thể làmlet boolValue = (let foo = bar)
Bryan Chen

ok nhưng để trích dẫn hướng dẫn Swift, trang 11, ví dụ là: if let name = optionName. optionName phải là một biểu thức, theo đó nếu optionName không phải là tùy chọn, nó sẽ đánh giá là true. Sau đó, phần thứ hai của câu lệnh bắt đầu bằng cách gán tùy chọn chưa được bao bọc cho tên. Vì vậy, câu hỏi đặt ra là, nếu "optionName không phải là tùy chọn" là một biểu thức, thì nó có thể được mở rộng bằng AND logic không. Btw Tôi nghĩ rằng bạn có thể đúng ở chỗ nó không thể được thực hiện.
Max MacLeod

-1

Tôi nghĩ đề xuất ban đầu của bạn không quá tệ. Một sự thay thế (lộn xộn) sẽ là:

if ((window!.rootViewController as? UITabBarController)?.viewControllers.count ?? 0) > 0 {
    println("do stuff")
}

1
nhưng bạn cần viết mã để truyền tabBarControllerlại
Bryan Chen
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.