Можливо, це дурне питання, але я ще не знайшов жодного рішення. Отже, моя проблема полягає в тому, що це протокол випромінювача подій з такою функцією:
mutating func on(eventName:String, action:((Any?)->())) {
//..
}
І я хочу використовувати його для інформування слухачів, коли подія викликається деякою інформацією. Токен доступу для події "login", наприклад.
appSessionHadler.on("login") { (weak data: String?) in
//...
}
І, ніж я отримую помилку, я не можу викликати "on" з цим списком аргументів типу. Звичайно, це працює з Any:
appSessionHadler.on("login") { (weak data: Any?) in
//...
}
Все відповідає Будь-який, Так що я "але заплутався. Може хтось пояснити це, будь ласка!"
Я міг би вирішити це за допомогою загального протоколу, але це все ще заважає мені, що він не працює так.
Відповіді:
2 для відповіді № 1Ви робите обіцянку, яку компілятор не може зберегти. The on
Ви можете зателефонувати action
з будь-якими даними взагалі. Але функція, яку ви передали, приймає String
. Що повинна робити система, якщо on
містить наступний код (прямо чи опосередковано):
action(1)
1
це не а String
, тому безпека типу буде порушена. Компілятор не може дозволити вам це зробити.
Інший спосіб подумати над цим - це on
приймає функцію типу F
, і ви проходите supertype від F
а не а підтип від F
. String
є підтипом Any
. Але параметри функціонують в зворотному порядку. (String)->Void
є супертипом (Any)->Void
. Таким чином, це те ж саме, що і передача змінної типу Any
функції, що вимагає String
. Формально ми говоримо, що функції в своїх параметрах контраваріантні і коваріантні у своїх зворотних значеннях. Ви можете прочитати більше про це в Відхилення типу в Swift.
Як ви підозрюєте, генерики тут правильні. Any
це майже завжди неправильний інструмент. І Any?
один з найважчих типів для роботи в Swift, тому я, безумовно, уникаю цього за будь-яку ціну. (Optional
є самим підтипом Any
і Swift має автоматичне просування до Optional
, так що це дуже часто, коли у вас є Any?
почати отримувати подвійні опції та гірше.)