Lỗi trình biên dịch Swift: Trường hợp enum có một bộ dữ liệu là một giá trị được liên kết, nhưng có một số mẫu ở đây


12

Xây dựng dự án trong Xcode 11.4 beta 3, tôi gặp lỗi Trình biên dịch Swift này trên enum:

Trường hợp enum có một bộ dữ liệu duy nhất là một giá trị được liên kết, nhưng có một số mẫu ở đây, ngầm ẩn các mẫu và cố gắng khớp với nó thay vào đó

Mã nguồn:

switch result {
case .error(let err):
    //
case .value(let staff, let locations):  // <-- error on this line
    //
}

Resultlà một enum chung với các giá trị liên quan cho .error.value. Trong trường hợp này, giá trị liên quan là một tupple.

public enum Result<T> {
    case value(T)
    case error(Error)
}

Đừng nhớ rằng đã thấy lỗi này trước đây và việc tìm kiếm nó không mang lại kết quả nào. Có ý kiến ​​gì không?


1
Tôi đã cập nhật câu hỏi, xin lỗi vì đã bỏ qua câu hỏi đó
Eneko Alonso

Không cần phải phát minh lại bánh xe Kết quả; nó đã tồn tại developer.apple.com/documentation/swift/result
matt

Ngoài ra, không có Xcode 11.4 beta 4 (chưa).
matt

Thật tệ, ý tôi là Xcode 11.4 beta 3. Liên quan đến Result, tôi đồng ý, đó là mã cũ có trước Swift.Result. Điều đó không có gì để làm với vấn đề, mặc dù.
Eneko Alonso

1
Tôi hoàn toàn đồng ý, tôi chỉ đang cố gắng làm sạch câu hỏi. Bạn nêu lên một điểm tốt ở đây và đây là cơ hội của chúng tôi để ghi lại các phương pháp chính xác cho người khác tìm thấy.
matt

Câu trả lời:


14

Tôi thấy bạn cũng có thể tắt lỗi này bằng cách xử lý giá trị được liên kết giống như một tuple bằng cách gói nó trong một bộ dấu ngoặc bổ sung:

switch result {
case .error(let err):
    //
case .value((let staff, let locations)):  
    //
}

1
Đó là tốt đẹp, tôi thích nó, cảm ơn bạn.
Eneko Alonso

2
Tuy nhiên, hãy cân nhắc việc di chuyển letra ngoài nếu bạn định ràng buộc mọi thứ: case let .value( (staff, locations) ):case .value( let (staff, locations) ):cả hai đều biên dịch. Chọn fave của bạn!
Jessy

1
Siêu nhỏ nhưng tôi không đồng ý với nhận xét trên về việc ràng buộc mọi thứ chỉ với một cho phép. Việc để bên trái của điều bị ràng buộc sẽ dễ đọc hơn và nhanh chóng hiểu những gì bị ràng buộc. Nếu không, bạn cần phải ngoại suy về mặt tinh thần những gì cho phép. Các nguyên tắc mã hóa của Google cho swift cũng khuyên bạn nên chống lại việc xếp tầng đơn lẻ: google.github.io/swift/#potype-matching
ToddH

2
Hướng dẫn "của Google": /
Gee.E

9

Ok, tìm ra nó. Có vẻ như enumvới các giá trị được liên kết, trong đó loại giá trị là một tupple, không còn có thể được khớp với câu lệnh chuyển đổi như thế:

// Works on Xcode 11.3.1, yields error on 11.4 (Swift 5.2)
switch result {
case .error(let err):
    //
case .value(let staff, let locations):  
    //
}

Giải pháp

Các giá trị từ tupple phải được trích xuất thủ công trong Xcode 11.4 (Swift 5.2):

// Works on Xcode 11.4
switch result {
case .error(let err):
    //
case .value(let tupple):  
    let (staff, locations) = tupple
    // 
}

Đó chắc chắn là một giải pháp.
matt

3

Đây là một vấn đề đã biết: https://developer.apple.com/documentation/xcode_release_notes/xcode_11_4_release_notes

Mã dựa trên trình biên dịch tự động theo dõi một mẫu có thể dẫn đến lỗi trình biên dịch khi nâng cấp lên Xcode 11.4, mặc dù mã đã được biên dịch trước đó. (58425942)

Ví dụ: bỏ dấu ngoặc đơn khi bật tùy chọn loại tuple gây ra lỗi trình biên dịch:

switch x { // error: switch must be exhaustive
case .some((let a, let b), let c): // warning: the enum case has a
     // single tuple as an associated value, but there are several
     // patterns here, implicitly tupling the patterns and trying
     // to match that instead
...

}

Giải pháp thay thế : Thêm dấu ngoặc đơn để thêm vào mẫu:

switch x {
case .some(((let a, let b), let c)): // Notice the extra pair of parentheses.
...

}


Cảm ơn thông tin bổ sung và liên kết đến ghi chú phát hành. Tôi đã bỏ lỡ nó.
Eneko Alonso

0

Nếu tôi có thể, tôi cũng muốn thêm câu trả lời cho if casephiên bản.

if case let .value(staff, error) = result {
    // Do something
}

và sau đó tất nhiên bỏ qua trường hợp:

if case let .value(staff, _) = result {
    // Do something
}
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.