Cung cấp giá trị mặc định cho Tùy chọn trong Swift?


141

Thành ngữ để xử lý các tùy chọn trong Swift dường như quá dài dòng, nếu tất cả những gì bạn muốn làm là cung cấp một giá trị mặc định trong trường hợp không có:

if let value = optionalValue {
    // do something with 'value'
} else {
    // do the same thing with your default value
}

liên quan đến việc sao chép mã không cần thiết hoặc

var unwrappedValue
if let value = optionalValue {
    unwrappedValue = value
} else {
    unwrappedValue = defaultValue
}

mà đòi hỏi unwrappedValuekhông phải là một hằng số.

Đơn vị Tùy chọn của Scala (về cơ bản là cùng một ý tưởng với Tùy chọn của Swift) có phương pháp getOrElsecho mục đích này:

val myValue = optionalValue.getOrElse(defaultValue)

Tui bỏ lỡ điều gì vậy? Swift đã có một cách nhỏ gọn để làm điều đó chưa? Hoặc, không thành công, có thể xác định getOrElsetrong tiện ích mở rộng cho Tùy chọn không?


Câu trả lời:


289

Cập nhật

Apple hiện đã thêm một nhà điều hành liên kết:

var unwrappedValue = optionalValue ?? defaultValue

Toán tử ternary là bạn của bạn trong trường hợp này

var unwrappedValue = optionalValue ? optionalValue! : defaultValue

Bạn cũng có thể cung cấp tiện ích mở rộng của riêng mình cho enum tùy chọn:

extension Optional {
    func or(defaultValue: T) -> T {
        switch(self) {
            case .None:
                return defaultValue
            case .Some(let value):
                return value
        }
    }
}

Sau đó, bạn có thể làm:

optionalValue.or(defaultValue)

Tuy nhiên, tôi khuyên bạn nên gắn bó với toán tử ternary vì các nhà phát triển khác sẽ hiểu điều đó nhanh hơn nhiều mà không phải điều tra orphương pháp

Lưu ý : Tôi đã khởi động một mô-đun để thêm các trình trợ giúp phổ biến như thế này orvào Optionalswift.


Trình biên dịch của tôi cho tôi thấy rằng loại unwrappedValuevẫn là loại tùy chọn cho trường hợp này trong Swift 1.2: var unwrappedValue = optionalValue ? optionalValue! : defaultValue(xcode 6 beta 4). Điều này đã thay đổi?
SimplGy

2
Tôi đã sai trên phiên bản của tôi. Tôi đang trên 6.4. Lưu ý: ??hành vi suy luận kiểu mặc định là nó trả về một tùy chọn, đây không phải là điều bạn muốn thông thường. Bạn có thể khai báo biến là không tùy chọn và điều này hoạt động độc đáo.
SimplGy

29

Kể từ tháng 8 năm 2014 Swift có nhà điều hành kết hợp (??) cho phép điều đó. Ví dụ: đối với Chuỗi tùy chọn myOptional bạn có thể viết:

result = myOptional ?? "n/a"

4

nếu bạn đã viết:

let result = optionalValue ?? 50

optionalValue != nilsau đó resultcũng sẽ như optionalvậy và bạn sẽ cần mở khóa nó trong tương lai

Nhưng bạn có thể viết toán tử

infix operator ??? { associativity left precedence 140 }

func ???<T>(optLeft:T?, right:T!) -> T!
{
    if let left = optLeft
    {
        return left
    }
    else { return right}
}

Bây giờ bạn có thể:

 let result = optionalValue ??? 50

Và khi optionalValue != nilđó resultsẽ làunwraped


3

Sau đây dường như làm việc

extension Optional {
    func getOrElse<T>(defaultValue: T) -> T {
        if let value = self? {
            return value as T
        } else {
            return defaultValue
        }
    }
}

tuy nhiên sự cần thiết phải value as Tlà một hack xấu xí. Tốt nhất, nên có một cách để khẳng định Tgiống như loại có trong Tùy chọn. Vì nó đứng, nhập các bộ suy luận Tdựa trên tham số được cung cấp cho getOrElse, và sau đó thất bại trong thời gian chạy nếu điều này không phù hợp với Tùy chọn và Tùy chọn không phải là không:

let x: Int?

let y = x.getOrElse(1.414) // y inferred as Double, assigned 1.414

let a: Int? = 5

let b: Double = a.getOrElse(3.14) // Runtime failure casting 5 to Double

Bạn không cần chỉ định Tcho phương thức. Điều đó thực sự ghi đè lên hiện có Ttừ Tùy chọn. Bạn chỉ có thể làm: func getOrElse(defaultValue: T) -> Tsau đó T đề cập đến loại giá trị thực của tùy chọn và bạn không phải gõ kiểm tra nó
drewag

Cảm ơn! Tôi đã suy luận chính xác điều đó từ nửa sau phản hồi của bạn. Có cách nào để kiểm tra định nghĩa của Tùy chọn để biết rằng loại chung được định nghĩa như Ttrong đó không? (vượt quá giả định đơn giản dựa trên quy ước)
Wes Campaigne

Nếu bạn nhấp chuột vào Optionalbên trong Xcode, bạn sẽ thấy rằng nó được xác định làenum Optional<T>
drewag

Ồ, tuyệt vời. Tôi nên đoán. Các định nghĩa trong đó sẽ hữu ích; có rất nhiều điều chưa có trong tài liệu này. Cảm ơn một lần nữa.
Wes Campaigne
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.