swift 5 загрузить несколько изображений и с параметром с пользовательским классом сетевого уровня - PullRequest
3 голосов
/ 26 апреля 2020

Я использую https://github.com/Mackis/NetworkLayer для сетевого процесса в моем приложении.

обычно я работаю так

networkManager.getServiceList { [weak self] (result, error) in
            guard let self = self else { return }
            if let error = error {
                print(error)

            }
            if let result = result {
                print(result)

            }
        }

, но когда дело доходит до загрузки нескольких изображений с параметрами я не мог понять это.

мой сценарий у меня есть 2 экрана. На первом экране я получаю значения, а затем отправляю второй v c

            self.newShop = ShopKurumsal(email: email as! String,
                                            name: (shopName as! String),
                                            cityId: city.value?.id,
                                            districtId: district.value?.id,
                                            address: (longAddress as! String),
                                            geoX: loc.coordinate.latitude,
                                            geoY: loc.coordinate.longitude,
                                            genderService: gender as? String,
                                            description: (description as! String),
                                            images: nil, price: self.selectedServices)
                let vc = PickImageViewController(networkManager: self.networkManager)
                vc.setShop(shop: self.newShop!)
                self.navigationController?.pushViewController(vc, animated: true)

, во втором v c только часть изображения. Я использую библиотеку YangMingShan для выбора изображений. Я получаю изображения и красиво показываю их в виде коллекции. Теперь мне нужно добавить к изображениям и вызвать конечную точку createShop, как это

networkManager.createShop(shop: self.newShop!) { [weak self] (result, error) in

        }

Мне нужно получить изображения на коллекцию и добавить в класс магазина как shop.append (images)

изображение Структура должна быть такой:

struct ShopImages: Codable {
    var imageName: String?
    var imageData: Data?
}

, а структура моего магазина -

struct ShopKurumsal: Codable {

    var email: String?
    var name: String?
    var cityId: Int?
    var districtId: Int?
    var address: String?
    var geoX: Double?
    var geoY: Double?
    var genderService: String?
    var description: String?
    var images: [ShopImages]?
    var price: [ShopPrice]?
}

, и здесь я выбираю изображения из библиотеки

   func photoPickerViewController(_ picker: YMSPhotoPickerViewController!, didFinishPickingImages photoAssets: [PHAsset]!) {

        picker.dismiss(animated: true) {

            let imageManager = PHImageManager.init()
            let options = PHImageRequestOptions.init()
            options.deliveryMode = .highQualityFormat
            options.resizeMode = .exact
            options.isSynchronous = true

            let mutableImages: NSMutableArray! = []

            for asset: PHAsset in photoAssets {
                print(asset)
                let scale = UIScreen.main.scale
                let targetSize = CGSize(width: (self.collectionview.bounds.width - 20*2) * scale, height: (self.collectionview.bounds.height - 20*2) * scale)
                imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options, resultHandler: { (image, info) in
                    mutableImages.add(image!)

                })
            }

            self.images = mutableImages.copy() as? NSArray
            self.collectionview.reloadData()
            self.hideLoading()

        }
    }

моего сетевого менеджера метод создания магазина подобен этому

func createShop(shop: ShopKurumsal, completion: @escaping (_ shop: ShopCreateRespons?,_ error: String?)->()){
    shopRouter.request(.createShop(model: shop)) { (data, response, error) in
        if error != nil {
            //completion(nil, "Please check your network connection.")
            completion(nil, error?.localizedDescription)

        }

        if let response = response as? HTTPURLResponse {
            let result = self.handleNetworkResponse(response)
            switch result {
            case .success:
                guard let responseData = data else {
                    completion(nil, NetworkResponse.noData.rawValue)
                    return
                }
                do {
                    print(responseData)
                    let jsonData = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers)
                    print(jsonData)
                    let apiResponse = try JSONDecoder().decode(ShopCreateRespons.self, from: responseData)
                    completion(apiResponse,nil)


                }catch {
                    print(error)
                    completion(nil, NetworkResponse.unableToDecode.rawValue)
                }
            case .failure(let networkFailureError):
                completion(nil, networkFailureError)
            }
        }
    }
}

конечная точка моего магазина

enum ShopNetworkEnvironment {
    case qa
    case production
    case staging
}

enum ShopApi {


    case createShop(model: ShopKurumsal)

}

extension ShopApi: EndPointType {

    var environmentBaseURL : String {
        switch NetworkManager.environment {
        case .production: return "https://api" 
        case .qa: return "https://api/" 
        case .staging: return "/api/" //test
        }
    }

    var baseURL: URL {
        guard let url = URL(string: environmentBaseURL) else { fatalError("baseURL could not be configured.")}
        return url
    }

    var path: String {
        switch self {

        case .createShop:
            return "Shop/RegisterShop"

        }
    }

    var httpMethod: HTTPMethod {
        switch self {
        case .getShops:
            return .get
        default:
            return .post
        }
    }

    var task: HTTPTask {
        switch self {

        case .createShop(let shop):
            return .requestParameters(bodyParameters: ["Email": shop.email as Any,
                                                       "Name": shop.name as Any,
                                                       "CityId": shop.cityId as Any,
                                                       "DistrictId": shop.districtId as Any,
                                                       "Address": shop.address as Any,
                                                       "GEOX": shop.geoX as Any,
                                                       "GEOY": shop.geoY as Any,
                                                       "GenderService": shop.genderService as Any,
                                                       "Description": shop.description as Any,
                                                       "Images": shop.images as Any,
                                                       "PriceList": shop.price as Any
                                                       ],
                                      bodyEncoding: .jsonEncoding, urlParameters: nil)


        default:
            return .request
        }
    }

    var headers: HTTPHeaders? {
        return nil
    }
}

тип конечной точки

protocol EndPointType {
    var baseURL: URL { get }
    var path: String { get }
    var httpMethod: HTTPMethod { get }
    var task: HTTPTask { get }
    var headers: HTTPHeaders? { get }
}

и маршрутизатор:

public typealias NetworkRouterCompletion = (_ data: Data?,_ response: URLResponse?,_ error: Error?)->()

protocol NetworkRouter: class {
    associatedtype EndPoint: EndPointType
    func request(_ route: EndPoint, completion: @escaping NetworkRouterCompletion)
    func cancel()
}

class Router<EndPoint: EndPointType>: NetworkRouter {
    private var task: URLSessionTask?

    func request(_ route: EndPoint, completion: @escaping NetworkRouterCompletion) {
        let session = URLSession.shared
        do {
            let request = try self.buildRequest(from: route)
            NetworkLogger.log(request: request)
            task = session.dataTask(with: request, completionHandler: { data, response, error in
                completion(data, response, error)
            })
        }catch {
            completion(nil, nil, error)
        }
        self.task?.resume()
    }

    func cancel() {
        self.task?.cancel()
    }

    fileprivate func buildRequest(from route: EndPoint) throws -> URLRequest {

        var request = URLRequest(url: route.baseURL.appendingPathComponent(route.path),
                                 cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
                                 timeoutInterval: 10.0)

        request.httpMethod = route.httpMethod.rawValue
        do {
            switch route.task {
            case .request:
                request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            case .requestParameters(let bodyParameters,
                                    let bodyEncoding,
                                    let urlParameters):

                try self.configureParameters(bodyParameters: bodyParameters,
                                             bodyEncoding: bodyEncoding,
                                             urlParameters: urlParameters,
                                             request: &request)

            case .requestParametersAndHeaders(let bodyParameters,
                                              let bodyEncoding,
                                              let urlParameters,
                                              let additionalHeaders):

                self.addAdditionalHeaders(additionalHeaders, request: &request)
                try self.configureParameters(bodyParameters: bodyParameters,
                                             bodyEncoding: bodyEncoding,
                                             urlParameters: urlParameters,
                                             request: &request)
            }
            return request
        } catch {
            throw error
        }
    }

    fileprivate func configureParameters(bodyParameters: Parameters?,
                                         bodyEncoding: ParameterEncoding,
                                         urlParameters: Parameters?,
                                         request: inout URLRequest) throws {
        do {
            try bodyEncoding.encode(urlRequest: &request,
                                    bodyParameters: bodyParameters, urlParameters: urlParameters)
        } catch {
            throw error
        }
    }

    fileprivate func addAdditionalHeaders(_ additionalHeaders: HTTPHeaders?, request: inout URLRequest) {
        guard let headers = additionalHeaders else { return }
        for (key, value) in headers {
            request.setValue(value, forHTTPHeaderField: key)
        }
    }

}
...