Какой у вас опыт сетевого взаимодействия в iOS?

«Какой у вас опыт сетевого взаимодействия в iOS?» — вопрос из категории Сети, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Опыт включает работу с различными аспектами сетевого слоя iOS-приложений.

Технологии и инструменты:

  • URLSession: Основной фреймворк для HTTP/HTTPS запросов (GET, POST, PUT, PATCH, DELETE), загрузки файлов, фоновых задач.
  • Codable: Стандартный протокол для сериализации и десериализации JSON.
  • Alamofire: Использование для упрощения сложных запросов, интерсепторов, валидации ответов.
  • WebSocket (URLSessionWebSocketTask): Для двустороннего real-time общения.
  • Аутентификация: Работа с Basic Auth, Bearer Token (JWT), OAuth 2.0.

Типичная архитектура сетевого слоя:

  1. Инкапсуляция в Service/Manager: Создание отдельных классов для групп запросов.
  2. Модели данных: Использование структур, соответствующих Codable.
  3. Обработка ошибок: Кастомные enum для ошибок сети и парсинга.
  4. Кэширование: Использование URLCache или ручное кэширование в базе данных.

Пример: GET-запрос с Codable и обработкой ошибок

struct User: Codable {
    let id: Int
    let name: String
}

enum NetworkError: Error {
    case invalidURL, noData, decodingError
}

func fetchUser(from urlString: String, completion: @escaping (Result<User, NetworkError>) -> Void) {
    guard let url = URL(string: urlString) else {
        completion(.failure(.invalidURL))
        return
    }

    URLSession.shared.dataTask(with: url) { data, response, error in
        if error != nil {
            completion(.failure(.noData))
            return
        }
        guard let data = data else {
            completion(.failure(.noData))
            return
        }
        do {
            let user = try JSONDecoder().decode(User.self, from: data)
            completion(.success(user))
        } catch {
            completion(.failure(.decodingError))
        }
    }.resume()
}

// Использование
fetchUser(from: "https://api.example.com/user/1") { result in
    switch result {
    case .success(let user):
        print("Пользователь: (user.name)")
    case .failure(let error):
        print("Ошибка: (error)")
    }
}

Best Practices: Использование async/await (iOS 15+), правильная отмена запросов, мониторинг сетевого состояния через Network.framework.