Pull to refresh

Comments 18

Интрига в заголовке заставила прочитать статью.

"Удалённый ресурс" оказался всего-лишь remote, а не removed или unlinked.


Но статья получилась хорошей

Спасибо и voidptr0. Странно, что мой ответ на его комментарий появился в этом месте.
1. Уже есть Swift 4 с Decodable, JSONSerialization не нужен
2. Использовать URLDownloadTask для API — не лучшая практика, захламлять систему одноразовыми файлами не стоит. DataTask для API был бы более логичен.
3. С форматированием кода (отступы) совсем беда.
4. NSAppTransportSecurity.NSAllowsArbitraryLoads — PLEASE NO! Используйте TLS для ВСЕГО, в самом крайнем случае разрешайте доступ без шифрования к ограниченному числу доменов…
5. Используйте weak вместо unowned, иначе легко словите Nil Unwrapping.
6. Force Unwrap (xxx!) — зло в любом виде, особенно (ОСОБЕННО) в декодировании данных из сторонних источников.
а можно подробнее про 6 пункт? как быть системе если данные не пришли?
Я не про систему, а про особенность Swift. Swift спроектирован как null-safe язык (привет Java-программистам с их NPE), и любые объекты, которые могут быть «null» объявляются как Type? (синтаксический сахар к Optional<Type>). Обращаться к таким объектам можно определёнными способами, и один из них — «force unwrap»:
let value: Type? = someFunc()
print(value) // выведет Optional(value) или nil
print(value!) // force unwrap - выведет value

Если в момент «force unwrap» значение переменной (или результата метода) окажется null (nil) — приложение завершит работу с Fatal Error.
Вывод — ВСЕГДА используйте optional unwrap и конструкции вида "if let x = optional { ... }" / "guard let x = optional else { ... ; return }"
На мой взгляд вывод неверен.
Может быть так что мы хотели бы иметь URL для какого-то объекта и инициализировать его из статичной строки. Если мы будем использовать guard let или if let, то не получим URL и можем потратить какое-то время на поиск ошибки, которая могла быть в опечатке строки для это URL. Но если бы мы использовали let url = URL(string: "https://habr.com")!, ошибку нашли бы на много быстрее, что было бы равносильно assert.
Если Вы хотите получить именно ошибку, то сделайте к примеру функцию, которая будет возвращать URL в случае успеха, либо выкидывать ошибку, которую Вы будете отлавливать и обрабатывать. Если Вы будете использовать:
let url = URL(string: "https://habr.com")!
в приложении, и строка будет неправильной, оно просто упадет, за что пользователи явно не скажут вам спасибо, а менеджер настучит по голове.
Есть исключения из любого правила. Статические URL к серверам API можно делать force-unwrap, и использовать ".appendingPathComponent" или «URL.init(_, baseURL:)». Вполне нормальная практика. Но все данные, которые могут прийти извне, надо валидировать optional-binding'ом или другими способами (Decodable в самый раз). Force unwrap — это крэш приложения. Он не уходит в do...catch и вообще никак не обрабатывается. Это зло, которое надо использовать ОЧЕНЬ осторожно.
Спасибо DjPhoeniX за развернутый комментарий.
1) На swift 4 все равно не могу написать, потому что мой компьютер не тянет. Об этом я писал. Но практика хорошая.
2) Вопрос к авторам книги, так как они используют URLDownloadTask исключительно в образовательных целях. Но и упоминают, что DataTask удобнее и короче.
3) Попытаюсь в следующих статьях это исправить.
4) Вот этого не знал. Буду изучать и использовать.
5) Так же не знал о различиях weak и unowned.
6) Не доглядел. В большем части кода, все-таки я использую безопасный optional binding.
Недочеты со временем исправлю.
Старый Mac или хакинтош без поддержки последней версии? И то и другое советую обновить. В любом случае в AppStore будут проблемы с не-последним SDK, да и в целом использовать Last Release более правильно.
По-моему какая-то жесть… Лучше почитайте эту статью или посмотрите как в Alamofire. И в этом коде:
self.window = UIWindow(frame: UIScreen.main.bounds) 

не задаете размер окна, а создаете новое, непонятно зачем…
Alamofire мне тоже нравится. Но я старался сохранить дух оригинальной книги.
В self.window… не вижу никакого жесткача.
Добрый день. Можете пояснить ситуацию, почему:
class RestRequest: NSMutableURLRequest {
}

let request = RestRequest() // падает
let request = NSMutableURLRequest() // работает

На ObjectiveC как-то без сюрпризов с конструктором
Подозреваю, что вы закрыли видимость для публичного конструктора родительского класса. Т.е. вам скорее всего надо добавить конструктор вида RestRequest() в ваш класс, вызывающий родительский конструктор
Изменения, внесенные в статью, по мере учета комментариев:
1) NSAppTransportSecurity позволяет загружать теперь только с домена, внесенного в исключения, а не со всех http сайтов, как это было ранее.
2) Убраны комментарии очевидных вещей. Оставлены только комментарии, поясняющие некоторые решения, например, необходимые в будущем. Сами комментарии включены в код, а не вынесены следом, как было ранее.
3) Код инициализации lazy var перенесен в них самих, а не в отдельные функции, как было ранее.
4) Сделал нормальное форматирование кода.
5) Почти все unwrapping сделал через guard. Оставил forse unwrapping только для свойства-замыкания и для обработки url.
6) Несмотря на кривость решения через download task и delegate, сохранил его, как памятник старины, чтобы знать, с чего все начиналось, и понять, чем современные решения лучше. Более современное решение будет показано в новой статье.
App Transport Security можно оставить полностью включенным, если URL заменить на HTTPS. На домене в статье он есть.
Sign up to leave a comment.

Articles

Change theme settings