Как стать автором
Обновить

Пишем свой сетевой слой на Swift: протокол-ориентированный подход

Время на прочтение10 мин
Количество просмотров31K
Всего голосов 17: ↑16 и ↓1+15
Комментарии11

Комментарии 11

забавно, мой ученик тот же апи использует. И тут даже слишком много кода.
Почитайте пожалуйста про парсинг json и camel Case.
Про парсинг я уже сам писал вот здесь, там кстати есть и про CamelCase и про snake
Десериализацию стоит вынести в дженерик метод чтобы при создании очередного эндпоинта всё не копипастить из router.request.
`NSURLSession` современный, гибкий, высокоуровневый, удобный, документированный, развивающийся API. Не вижу смысла использовать что-то ещё поверх него. Вам реально кажется таким полезным вместо `«POST»` писать `.POST`? Или `.count(5)` настолько лучше, чем `URLQueryItem(parameter: «count», value: «5»)`, несмотря на то, что теперь чтобы добавить новый параметр в вызов, нужно два места в коде менять?

При этом все эти украшательства искусственно ограничивают доступные возможности. Потом эти возможности либо а) не используются б) обрастают дублирующими «своими» API-обёртками.

Вместо просто использования стандартных API, разработчики, приходя на такой проект, вынуждены разбираться в особенностях очередного «фреймворка».
Вы правда думаете, что запрос такого вида, как тот что ниже, будет проще для использования в коде чем одна строчка с хорошо читаемым форматом?

Да, я специально немного утрировал пример, можно создать функции для get и post запросов с входными параметрами, можно сделать функции для каждого конкретного запроса и т.д., но чем больше вы будете пытаться сделать слой универсальным, гибким и простым в использовании, тем больше вы будете приближаться к чему-то похожему на эту статью. В больших проектах вызовы запросов встречаются в сотнях мест, и даже небольшое сокращение кода при работе с запросами и более понятный и читаемый синтаксис могут принести огромную пользу. Вносить изменения в такой слой тоже, наоборот, легче, вам надо например поменять стандартный хедер в get-запросах, тип кодировки или еще что-то подобное, вы его поменяете всего в одном месте, никаких проблем. И эти «украшательства» абсолютно ничем не ограничивают возможности, их никто не отнимал, добавляйте что хотите. И для новых разработчиков такой «фреймворк» не принесет никакого неудобства, наоборот, пользоваться им проще некуда, написать его непросто, а пользоваться им уж точно не сложно + такой подход защитит от самодеятельности этих самых новых разработчиков, в то время как дав им возможность реализовать запросы через URLSession в том виде в каком они хотят однозначно приведет к тому что каждый реализует как бог пошлет. Жить безусловно можно и с URLSession, но так — намного удобнее.

let config = URLSessionConfiguration.default

let session = URLSession(configuration: config)

let url = URL(string: "https://httpbin.org/anything")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"

// your post request data
let postDict : [String: Any] = ["name": "axel",
                                "favorite_animal": "fox"]

guard let postData = try? JSONSerialization.data(withJSONObject: postDict, options: []) else {
    return
}

urlRequest.httpBody = postData

let task = session.dataTask(with: urlRequest) { data, response, error in
	
    // ensure there is no error for this HTTP response
    guard error == nil else {
        print ("error: \(error!)")
        return
    }
	
    // ensure there is data returned from this HTTP response
    guard let content = data else {	
        print("No data")
        return
    }
	
    // serialise the data / NSData object into Dictionary [String : Any]
    guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
        print("Not containing JSON")
        return
    }
	
    print("gotten json response dictionary is \n \(json)")
    // update UI using the response here
}

// execute the HTTP request
task.resume()

Стоит один раз задуматься о том, что и NSURLSession тоже был сделан, чтобы скрыть некоторую сложность. И по-хорошему, на нём вполне можно и остановиться, используя практически в чистом виде, без каких-либо своих обёрток.

По построению такой «роутер» поддерживает отмену только последнего запроса, причём это не очевидно, это может вылиться в ужасно непонятные ошибки в работе
В каждой функции типа getNewMovies будет происходить одно и то же. Поэтому, данную обработку ответа к конкретному типу я бы вынес тоже в сетевой слой. Ну либо в слой поверх сетевого (тут каждому уж свое). Вот, почитать: habr.com/ru/post/338380
Почему-то есть ощущение, что Alamofire переписан «немного другими словами»
скорее уж Moya
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории