Как вы должны обрабатывать аргументы закрытия для UIAlertAction

Я пытаюсь создать UIAlertAtion, который также имеет обработчик. Я прочитал ответы из этого вопроса и знаю, как это сделать.

Мой вопрос касается только его закрывающей части.

1) Я знаю, что могу написать: {alert in println("Foo")} Или {_ in println("Foo")}, но я не могу написать {println("Foo")}. В комментариях здесь это объясняется тем, что вам нужно обработать действие с аргументом.

Означает ли это, что, поскольку обработчик имеет тип (UIAlertAction) -> Void)?, я должен всегда захватывать переданный alertAction?


2) Я также читаю этот, и в основном ответ заключается в том, что вы можете передать функцию как свой аргумент, но функция должна взять что-то типа UIAlertAction -> Void, которое я написал:

private func anything(action : UIAlertAction) {
    print("hello")
}

а затем написал мое предупреждение как таковое:

let anotherAction = UIAlertAction(title: "hi", style: UIAlertActionStyle.Default,
 handler: anything(action)) // error: Use of unresolved identifier 'action'

confused, почему я получаю эту ошибку


3) В комментариях он также сказал: Но в дополнение к этому вам не нужно писать UIAlertActionStyle.Default в быстром..Default тоже работает.

Я пробовал писать, не используя стиль, поэтому он будет по умолчанию .Default

let sendLogAction = UIAlertAction(title: "Log") { action in print("goodbye")}

Но затем я получаю следующую ошибку:

'(title: String, (_) → ())' (aka '(title: String, _ → ())') не является convertible to '(название: String?, style: UIAlertActionStyle, обработчик: ((UIAlertAction) → Void)?) '(Aka' (название: необязательно, стиль: UIAlertActionStyle, обработчик: необязательный() > ) '), кортежи имеют различное количество элементов


4) Также читайте этот ответ. Я не понимаю, зачем нам проходить в alert, это не имеет смысла. Это не похоже на то, что мы не знаем, что такое тип предупреждения... разве мы уже не определили его тип?!! Может ли кто-нибудь объяснить, когда передача самого действия будет полезной вообще, я имею в виду, что мы можем с ней сделать?


Я знаю, что это написано как 4 вопроса, но я думаю, что это действительно просто основополагающий вопрос. Я широко читал, использовал обработчики закрытия/завершения в проекте, который я работаю и играю на детской площадке, но все же я в замешательстве.

Ответ 1

  • Да, вы должны всегда обрабатывать аргумент. Это часть подписи и не может быть проигнорирована. Кроме того, специальный синтаксис Swift может отбрасывать параметр handler, поскольку он является последним параметром и является параметром закрытия.

  • Измените anything(action) на anything так же, как в примере, на который вы ссылаетесь.

  • Вы неправильно поняли. Они не говорят, что вы можете отказаться от параметра стиля. Они говорят, что вы можете отказаться от UIAlertActionStyle от UIAlertActionStyle.Default, что означает, что вам нужно передать .Default в качестве аргумента в параметр стиля.

  • Вам нужен пример использования параметра action для обработчика. На самом деле не так уж много применений. Единственными свойствами являются название, стиль и включен ли он или нет. Последнее бессмысленно, потому что, если обработчик был вызван, вы знаете, что он включен. Единственное возможное использование - если заголовок или стиль должны использоваться в обработчике, и они не были жестко закодированы в действие предупреждения, когда оно было создано. Получив доступ к свойствам заголовка или стиля в обработчике, вы легко получаете доступ к фактическим значениям, используемым при создании действия.

Ответ 2

1) Определение метода инициализации UIAlerAction принимает 3 аргумента, а последний аргумент (UIAlertAction → Void)? что означает, что у вас может быть функция no-name (или закрытие) или нуль (задается необязательным символом?). Если вы решите не указывать последний аргумент, вы можете таким образом отобразить UIAlertController

alert.addAction(UIAlertAction(title: "test", style: .default, handler: nil))

но если вы хотите указать последний аргумент (не nil), тогда вы должны предоставить закрытие, которое принимает UIAlertAction в качестве аргумента и ничего не возвращает (Void). Ссылаясь на вашу ссылку, он просто использует "постоянную оповещения, которую он уже создал для простоты".

Чтобы ответить на ваш вопрос "Означает ли это..., ответ Да, из-за определения третьего аргумента: (UIAlertAction) → Void)?

2) Вы получаете ошибку, потому что передаете аргумент (действие). Попробуйте

anotherAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default,
 handler: anything)

и вы не должны ошибаться.

3) UIAlertAction имеет только (я считаю) один метод init, поэтому вам нужно предоставить все три аргумента для его создания. см. мой 1) ответ для стиля:.default. Это новый способ вызова Swift Enums. Кстати, все перечисления должны быть в нижнем регистре, поэтому .default not. Код Default`enter здесь

alert.addAction(UIAlertAction(title: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Void))

4) Как вы можете видеть из ответа, у вас есть ссылка. Вы можете использовать постоянное "предупреждение" (UIAlertAction), чтобы делать с ним все, что хотите, например, проверять стиль и делать некоторые вещи.

func anything(alert: UIAlertAction!) {
    print("somehandler")
    switch alert.title {
    case "OK"?:
      print("title is OK")
    default:
      print("title is not OK")
    }
  }

Ответ 3

rmaddy answer достаточно, но являюсь OP:) Я нахожу основную причину моего вопроса:

Недостаток в понимании обработчика параметров, обработчик имеет тип: (UIAlertAction) -> Void)? т.е. замыкание/функция

Обработчик ожидает только имя функции, как только вы предоставите эту функцию, она заполнит входы этой функции .

вы передаете anything только как обработчик, т.е. имя функции.

Внутренняя реализация UIAlertAction имеет некоторую строку типа handler(action), которая использовала бы anything, которая имеет тип (UIAlertAction) -> Void)?, вставляет action (который передается на нее), в итоге делая anything(action).

Как говорится, ваш anything(input: UIAlertAction) должен делать что-то значимое. (уже обсуждался в комментариях с rmaddy)


Другое решение - не предоставлять функцию, а вместо этого использовать захваченное действие в трейлинг-закрытии и делать с ним все, что вам нравится.

let retryAction = UIAlertAction(title: returnTitle(), style: UIAlertActionStyle.Default) { action in
switch action.title {
        case "OK":
        okFunc()
        case "cancel":
        cancelFunc()
        default:
        defaultFunc()
        }
      }

Такое переключение полезно только в том случае, если вы получаете код динамически, иначе нет переключения добавленного значения для плитки, которую вы знаете ее значение.