В документах есть пример расширения для добавления безопасного и неизвестного доступа к любому индексу (реальному или воображаемому) массива Swift (Edit - SO Docs больше не существует, поэтому этот пример был вставлен внизу этого вопроса ).
Массивы Swift обычно аварийно завершают работу, если индекс не существует. Похоже, это расширение специально предназначено для решения этой проблемы, возвращая nil
, если в запрошенном индексе ничего нет.
Расширение выглядит так:
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
Использование расширения выглядит следующим образом:
if let thirdValue = array[safe: 2] {
print(thirdValue)
}
Попытка этого на игровых площадках не показывает ничего возвращающегося для небезопасного индекса. Это я могу сказать. Ни факультатив, ни ноль, ничего. И никакого краха.
Как это не является необязательным, что возвращается из этого, когда это безопасное или небезопасное значение индекса? Я восхищаюсь тем, что это работает, просто не очень понимаю, как это работает или что оно делает.
ОБНОВИТЬ
Как услужливо отмечает Мартин Р, большая часть моей проблемы заключается в том, чтобы не понимать/не помнить/знать, что if let
совершает принудительное развертывание необязательного параметра, который является результатом функции расширения, возвращающей значение, которое определенно является необязательным. Если эта принудительная распаковка не раскрывает значение (т. е. ни одно значение в индексе не возвращает необязательное значение, содержащее nil
), это предотвращает вызов {trailing closure}
.
Однако возникает еще один подвопрос.
Если вы используете переменную для захвата возвращаемого значения, например:
let val = array[safe: 2]
print("val:", val)
независимо от результата, это необязательно, но Swift выдает «полезную» ошибку:
Выражение, неявно полученное из 'Int?' любому
Прошу прощения, если это должен быть новый вопрос: почему это принуждают к Any
? Почему нельзя (и почему бы и нет) просто оставаться необязательным типом Int?
Следующее содержимое взято из «Безопасный доступ к индексам» из документации по переполнению стека (заархивировано здесь); авторские права 2017 г. принадлежат Moriya; под лицензией CC BY-SA 3.0. Архив полного содержимого документации Stack Overflow можно найти на сайте archive.org, где этот пример проиндексирован по идентификатору темы: 284, например: 16567.
Добавляя следующее расширение к индексам массива, можно получить доступ, не зная, находится ли индекс внутри границ.
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
пример:
if let thirdValue = array[safe: 2] {
print(thirdValue)
}