Як швидко зробити необов’язкове закриття?


93

Я намагаюся оголосити аргумент у Swift, який приймає необов'язкове закриття. Функція, яку я оголосив, виглядає приблизно так:

class Promise {

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

}

Але Свіфт скаржиться, що "Прив’язане значення в умовному випадку має бути необов'язковим типом", де оголошено "якщо дозволено".


Подумайте про використання лише одного закриття з параметрами.
catanore

Відповіді:


113

Вам слід додати необов’язкове закриття в дужки. Це належним чином охопить ?оператора.

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

Чи знаєте ви, що обгрунтовується необхідність вкладати його в дужки?
Маркоск

5
Можливо, щоб зняти неоднозначність. Якщо необов'язкове закриття мало б повернути значення, воно може заплутатися в тому, що ()->Int?означає.
Цезар

3
Також із книги Swift: "Оголошуючи необов’язковий тип, не забудьте скористатися дужками для належного застосування області? оператор. Як приклад, щоб оголосити необов'язковий масив цілих чисел, напишіть анотацію типу як (Int []) ?; написання Int []? видає помилку ".
Цезар

@Cezar Чи не могли б ви пояснити трохи, чому і де використовувати "Необов’язкове закриття", мені цікаво це знати.
iLearner

@Cezar На даний момент не на комп'ютері Mac, тому мій синтаксис може бути трохи відключений, але пам'ятайте, що ?насправді це просто цукор Optional<T>, тому ви також можете написати `func тоді (onFulfilled: () -> (), onReject: Необов'язково <() -> ()>) {`тоді зайві вам не знадобляться (), хоча ІМО тим ()?гарніший. Крім того, ви можете зробити її ще гарнішою з подібними типами typealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Ендрю Картер,

62

Щоб зробити код ще коротшим, ми можемо використовувати його nilяк значення за замовчуванням для onRejectпараметра та додаткового ланцюга ?()при його виклику:

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

Таким чином, ми можемо опустити onRejectпараметр, коли ми викликаємо thenфункцію.

then({ /* on fulfilled */ })

Ми також можемо використовувати синтаксис закриття для завершення передачі onRejectпараметра у thenфункцію:

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

Ось повідомлення про це в блозі .


34

Оскільки я припускаю, що це "необов'язкове" закриття просто не повинно нічого робити, ви можете використовувати параметр із порожнім закриттям як значення за замовчуванням:

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

цю функцію тепер можна викликати із onRejectзворотним дзвінком або без нього

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

Тут не потрібно чудового Свіфта Optionals?!


Це приємне рішення!
Роланд Т.

6

Можливо, це чистіший спосіб. Особливо, коли закриття має складні параметри.

typealias SimpleCallBack = () -> ()

class Promise {

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

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.