Как быстро сделать необязательное закрытие?


93

Я пытаюсь объявить аргумент в Swift, который требует дополнительного закрытия. Объявленная мною функция выглядит так:

class Promise {

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

}

Но Swift жалуется, что «связанное значение в условном выражении должно быть необязательным типом», где объявлено «if let».


Рассмотрите возможность использования только одного закрытия с параметрами.
catanore

Ответы:


113

Вы должны заключить необязательное закрытие в круглые скобки. Это позволит правильно определить область действия ?оператора.

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

Знаете ли вы, в чем причина необходимости заключать это в круглые скобки?
Marcosc

5
Наверное, чтобы убрать двусмысленность. Если бы необязательное закрытие должно было иметь возвращаемое значение, это могло бы сбить с толку, что ()->Int?означает.
Cezar

3
Кроме того, из книги Swift: «При объявлении необязательного типа обязательно используйте круглые скобки, чтобы правильно указать? оператор. Например, чтобы объявить необязательный массив целых чисел, запишите аннотацию типа как (Int []) ?; писать Int []? выдает ошибку. "
Cezar

@Cezar Не могли бы вы немного объяснить, почему и где использовать «Необязательное закрытие», мне любопытно это узнать.
iLearner

@Cezar На данный момент нет на Mac, поэтому мой синтаксис может быть немного неправильным, но помните, что на ?самом деле это просто сахар Optional<T>, поэтому вы также можете написать `func then (onFulfilled: () -> (), onReject: Optional <() -> ()>) {`тогда вам не понадобится лишнее (), хотя, по-моему, ()?он красивее. Также вы можете сделать его еще красивее с помощью типажей вроде typealias RejectHandler = () -> () func then(onFulfilled: ()->(), onReject: RejectHandler?) {
Эндрю Картер,

63

Чтобы сделать код еще короче, мы можем использовать 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: { ... })

Здесь нет нужды в крутом Swift Optionals?!


Хорошее решение!
Roland T.

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.