Я начал использовать swiftLint и заметил, что одна из лучших практик для Свифт, чтобы не бросить силы. Однако я использовал его много, когда обработка TableView, в collectionView для клеток :
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellID, forIndexPath: indexPath) as! MyOffersViewCell
Если это не лучшая практика, что's не правильный путь, чтобы справиться с этим? Я думаю, я могу использовать, если да как?, но это значит, что для другого состояния я нужно вернуть пустую ячейку? Это приемлемо?
if let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellID, forIndexPath: indexPath) as? MyOffersViewCell {
// code
} else {
// code
}
Этот вопрос, наверное, мнение, основанное, так что примите мой ответ с зерном соли, но я бы'т сказать, что силы потупив всегда плохо; вы просто должны рассмотреть семантику и как это применимо в данной ситуации.
как! SomeClass` - это контракт, он в основном пишет "Я гарантирую, что эта штука экземпляр SomeClass" по. Если выяснится, что это'т SomeClass, то будет выброшено исключение, потому что вы нарушили договор.
Нужно учитывать контекст, в котором вы используете этот договор и какие действия можно предпринять, если вы не'т использовать силу потупив.
В примере, вы даете, если dequeueReusableCellWithIdentifier*не'т* дать вам
MyOffersViewCell-тогда вы, наверное, неправильно как-то связано с сотового повторного использования идентификатора и исключение поможет вам найти этот вопрос.
Если вы использовали условное потупив затем вы собираетесь получить ноль и придется с этим разбираться как-то - войти в сообщение? Бросать исключение? Это, конечно, представляет собой неустранимую ошибку и то, что вы хотите найти во время разработки, вы бы'т ждать, чтобы справиться с этим после релиза. Ваш код-это'т собираюсь вдруг начать возвращать различные типы клеток. Если вы просто дайте крушения код на силу потупив, он будет указывать прямо на линии, где проблема произошла.
Теперь рассмотрим случай, когда вы обращаетесь к некоторым формате JSON, полученных из веб-сервиса. Там может быть изменение в веб-сервис, который находится вне вашего контроля, поэтому обращение это более изящно было бы хорошо. Ваше приложение может не работать, но по крайней мере вы можете показать предупреждение, а не просто сбой:
Плохо - падает, если в JSON это'т массив
let someArray=myJSON as! NSArray
...
Лучше - ручка поврежденных JSON с предупреждение
guard let someArray=myJSON as? NSArray else {
// Display a UIAlertController telling the user to check for an updated app..
return
}
Обновление
После использования Swiftlint на некоторое время, я сейчас всего преобразовать в нулевую силу-разворачивание назначения (в соответствии с @Кевин'ы комментарий ниже).
Там действительно не'т любой ситуации, когда вам надо разворачивать необязательно, что вы можете'т использовать если бы...
, охранник... давайте еще
, или `перейти... случае давайте... вместо того, чтобы.
Итак, сегодня я хотел бы сделать это:
for media in mediaArray {
if let song = media as? Song {
// use Song class's methods and properties on song...
} else if let movie = media as? Movie {
// use Movie class's methods and properties on movie...
}
}
...или, если вы предпочитаете элегантность и безопасность заявлении исчерпывающий выбрать более подвержены ошибкам цепь `если/еще, тогда:
switch media {
case let song as Song:
// use Song class's methods and properties on song...
case let movie as Movie:
// use Movie class's methods and properties on movie...
default:
// Deal with any other type as you see fit...
}
...или лучше, использовать помощью flatMap()в свою очередь
mediaArray на два (возможно, пустых) набирается массивы типов[песня] " и " [кино]` соответственно. Но это выходит за рамки вопроса (форс-разверни)...
Кроме того, я выиграл'т заставить развернуть даже при удалении из очереди табличный вид клеток. Если удалены из очереди ячейки не может быть приведен к соответствующему инструменту UITableViewCell
подкласс, значит что-то не так с моей раскадровки, так что's не время выполнения некоторых условий можно восстановить (вернее, разработке-ошибки времени выполнения, которые должны быть обнаружены и исправлены), так что я залог с ошибку fatalerror()
.
Оригинальные ответы (по записи)
В дополнение к Paulw11'ы ответьте, этот шаблон является полностью допустимым, безопасным и полезным иногда:
if myObject is String {
let myString = myObject as! String
}
Рассмотрим пример, приведенный Яблоко: массив экземпляры средства массовой информации, которые могут содержать либо песня
и кино
объектов (подклассы СМИ):
let mediaArray = [Media]()
// (populate...)
for media in mediaArray {
if media is Song {
let song = media as! Song
// use Song class's methods and properties on song...
}
else if media is Movie {
let movie = media as! Movie
// use Movie class's methods and properties on movie...
}
"в силу бросания" есть свое место, когда вы *знаете *** то, что вы'вновь бросая к такого рода например.
Сказать, что мы знаем, что как myview
имеет подпанели, что это UILabel ни с тэгом 1
, мы можем идти вперед и сбивать литой из наследник UIView
до UILabel ни
по безопасности:
myLabel = myView.viewWithTag(1) as! UILabel
Кроме того, более безопасным вариантом является использование предохранителя.
guard let myLabel = myView.viewWithTag(1) as? UILabel else {
... //ABORT MISSION
}
Последний является более безопасным, так как он, очевидно, обрабатывает любые плохие дела, но и бывшей, легче. Так что это действительно сводится к личным предпочтениям, с учетом того, что его что-то может измениться в будущем, или если вы'ре не уверен в том, что вы не разворачивала будет то, что вы хотите бросить, то в этой ситуации охранник всегда был бы правильный выбор.
Подводя итог: Если вы точно знаете, что это будет потом вас могут заставить бросить, в противном случае если есть малейший шанс это может быть что-то другое использовать предохранитель
Другие писали о более общем случае, но я хочу дать мое решение в конкретном случае:
guard let cell = tableView.dequeueReusableCell(
withIdentifier: PropertyTableViewCell.reuseIdentifier,
for: indexPath) as? PropertyTableViewCell
else {
fatalError("DequeueReusableCell failed while casting")
}
В основном, оберните его вокруг заявление защита
и бросил его дополнительно с как?
.
Когда вы работаете с вашими типами и уверены, что они имеют ожидаемый тип и всегда имеют значения, он должен заставить бросить. Если крах вашего приложения, вы можете легко узнать, у вас есть ошибка, на которой часть интерфейса, удаление клеток, ...
Но когда вы собираетесь бросить видах, что вы Дон'т знаем, что это всегда один и тот же тип? Или это то, что всегда имеет ценность? Вы должны избежать силы развернуть
Как JSON, который приходит от сервера, что вы'т знаете, какой тип заключается в том, что ни один из ключей, которые имеют ценность или нет
Извините за мой плохой английский я пытаюсь себя улучшить
Удачи🤞🏻
В тех случаях, когда вы действительно уверены, что объект должен быть определенного типа, было бы ОК, чтобы бросить вниз. Однако, я использую следующие глобальные функции в этих случаях, чтобы получить более значимые результаты в журналах, которые в моих глазах лучший подход:
public func castSafely<T>(_ object: Any, expectedType: T.Type) -> T {
guard let typedObject = object as? T else {
fatalError("Expected object: \(object) to be of type: \(expectedType)")
}
return typedObject
}
Пример использования:
class AnalysisViewController: UIViewController {
var analysisView: AnalysisView {
return castSafely(self.view, expectedType: AnalysisView.self)
}
override func loadView() {
view = AnalysisView()
}
}