Làm thế nào để thực hiện một đóng cửa tùy chọn nhanh chóng?


93

Tôi đang cố gắng khai báo một đối số trong Swift có một đóng tùy chọn. Hàm tôi đã khai báo trông như thế này:

class Promise {

 func then(onFulfilled: ()->(), onReject: ()->()?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }

}

Nhưng Swift phàn nàn rằng "Giá trị ràng buộc trong một điều kiện phải là loại Tùy chọn" trong đó "if let" được khai báo.


Hãy xem xét chỉ sử dụng một bao đóng với các tham số.
catanore

Câu trả lời:


113

Bạn nên đặt phần đóng tùy chọn trong dấu ngoặc đơn. Điều này sẽ xác định phạm vi chính xác của ?nhà điều hành.

func then(onFulfilled: ()->(), onReject: (()->())?){       
    if let callableRjector = onReject {
      // do stuff! 
    }
 }

Bạn có biết cơ sở lý luận của việc phải đặt nó trong ngoặc đơn là gì không?
Marcosc

5
Có lẽ là để loại bỏ sự mơ hồ. Nếu bao đóng tùy chọn có giá trị trả về, nó có thể gây nhầm lẫn về ý ()->Int?nghĩa.
Cezar

3
Ngoài ra, từ cuốn sách Swift: “Khi khai báo một kiểu tùy chọn, hãy đảm bảo sử dụng dấu ngoặc đơn để xác định đúng phạm vi? nhà điều hành. Ví dụ, để khai báo một mảng số nguyên tùy chọn, hãy viết chú thích kiểu là (Int []) ?; viết Int []? tạo ra một lỗi. "
Cezar

@Cezar Bạn có thể vui lòng giải thích một chút tại sao và nơi sử dụng "Đóng cửa tùy chọn", tôi rất tò mò muốn biết điều này.
iLearner

@Cezar Hiện tại không có trên mac nên cú pháp của tôi có thể hơi sai, nhưng hãy nhớ rằng ?thực sự chỉ là đường cho Optional<T>, vì vậy bạn cũng có thể viết `func then (onFulfilled: () -> (), onReject: Tùy chọn <() -> ()>) {`thì bạn sẽ không cần thêm (), mặc dù IMO ()?thì đẹp hơn. Ngoài ra, bạn có thể làm cho nó thậm chí còn đẹp hơn với một kiểu chữ như typealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Andrew Carter

62

Để làm cho mã ngắn hơn nữa, chúng ta có thể sử dụng nillàm giá trị mặc định cho onRejecttham số và chuỗi tùy chọn ?()khi gọi nó:

func then(onFulfilled: ()->(), onReject: (()->())? = nil) {
  onReject?()
}

Bằng cách này, chúng ta có thể bỏ qua onRejecttham số khi chúng ta gọi thenhàm.

then({ /* on fulfilled */ })

Chúng ta cũng có thể sử dụng cú pháp bao đóng theo sau để truyền onRejecttham số vào thenhàm:

then({ /* on fulfilled */ }) {
  // ... on reject
}

Đây là một bài đăng trên blog về nó.


34

Vì tôi giả sử rằng, việc đóng "tùy chọn" này chỉ đơn giản là không làm gì cả, bạn có thể sử dụng một tham số với một bao đóng trống làm giá trị mặc định:

func then(onFulfilled: ()->(), onReject: ()->() = {}){       
    // now you can call your closures
    onFulfilled()
    onReject()
}

chức năng này bây giờ có thể được gọi có hoặc không có lệnh onRejectgọi lại

then({ ... })
then({ ... }, onReject: { ... })

Không cần Swift tuyệt vời Optionals?ở đây!


Đây là giải pháp tốt đẹp!
Roland T.

6

Có lẽ đó là một cách sạch hơn. Đặc biệt khi việc đóng cửa có các tham số phức tạp.

typealias SimpleCallBack = () -> ()

class Promise {

func then(onFulfilled: SimpleCallBack, onReject: SimpleCallBack?){       
    if let callableRjector = onReject {
        // do stuff! 
    }
}

}
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.