Вызовите одну и ту же веб-службу несколько раз из разных контроллеров представления (не одновременно) в ios - PullRequest
0 голосов
/ 08 мая 2018

Мне было просто интересно, как лучше всего вызвать один и тот же веб-сервис с разных контроллеров представления (в разное время). Какой архитектуре или дизайну я должен следовать? Я не хочу писать один и тот же код в каждом контроллере вида.

Ответы [ 5 ]

0 голосов
/ 08 мая 2018

Никогда не передавайте свой Views и / или ViewControllers вам NetworkManager класс.Предположим, у вас есть класс NetworkManager, подобный этому.

open class NetworkHelper {

    class var sharedManager: NetworkHelper {
        struct Static{
            static let instance: NetworkHelper = NetworkHelper()
        }
        return Static.instance
    }

    func request(_ method: HTTPMethod, _ URLString: String, parameters: [String : AnyObject]? = [:], headers: [String : String]? = [:], completion:@escaping (Any?) -> Void, failure: @escaping (Error?) -> Void) {

        let URL = "BASE_PATH" + "URLString"
        Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
            .responseJSON { response in

                switch response.result {
                case .success:
                    completion(response.result.value!)
                case .failure(let error):
                    failure(error)
                    guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
                        return
                    }

                }
        }
    }
}

Теперь создайте BaseViewController, который наследуется от UIViewController, и напишите свой вызов API с необходимыми параметрами.Например, в вызове API вам нужен только userID, поскольку в качестве параметра все остальное равно static.

class BaseViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

    }
    func makeThisApiCallWithUserID(userId: Int) {
        NetworkHelper.sharedManager.request(.get, "api/v1/yourApiAddress", parameters: ["userId":userId as AnyObject],headers: ["Authorization":"Bearer agshd81tebsf8724j"], completion: { (response) in

        }) { (error) in

        }
    }
}

Нет, вы не должны наследовать те ViewController, в которых вы хотите тот же вызов API, и вы не делаетехочу снова написать код.

class FirstChildViewController: BaseViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.makeThisApiCallWithUserID(userId: 123)
    }
}
class SecondChildViewController: BaseViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.makeThisApiCallWithUserID(userId: 13)
    }
}
class ThirdChildViewController: BaseViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.makeThisApiCallWithUserID(userId: 3)
    }
}

Видите, я не писал код API в FirstChildViewController, SecondChildViewController, ThirdChildViewController, но все же они могут выполнять один и тот же вызов API с разными параметрами.

0 голосов
/ 08 мая 2018

Создайте базовый класс для запроса Alamofire следующим образом:

import Alamofire

/// Struct for create AlamofireRequestModal
struct AlamofireRequestModal {
    /// Struct constant for Alamofire.HTTPMethod
    var method: Alamofire.HTTPMethod
    /// Struct constant for path
    var path: String
    /// Struct constant for parameters
    var parameters: [String: AnyObject]?
    /// Struct constant for encoding:ParameterEncoding
    var encoding: ParameterEncoding
    /// Struct constant for headers
    var headers: [String: String]?

    ///method to get init
    init() {
        method = .post
        path = ""
        parameters = nil
        encoding = JSONEncoding() as ParameterEncoding
    }
}

///BaseService to call the api's
class BaseService: NSObject {
    /// network variable for Reachability
    let network = Reachability.init(hostname: "https://www.google.com")

    /**
     This is method for call WebService into Alamofire

     - parameter alamoReq: this is AlamofireRequestModal type request
     - parameter success: success response
     - parameter failure: failer object
     */
    func callWebServiceAlamofire(_ alamoReq: AlamofireRequestModal, success:@escaping ((_ responseObject: AnyObject?) -> Void), failure:@escaping ((_ error: NSError?) -> Void)) {
        guard (network?.isReachable)! else {
            debugPrint("\n No Network Connection")
            return
        }

        let request = Alamofire.request(alamoReq.path, method: alamoReq.method, parameters: alamoReq.parameters, encoding: alamoReq.encoding, headers: alamoReq.headers)
        // Call response handler method of alamofire
        request.validate(statusCode: 200..<600).responseJSON(completionHandler: { response in
            let statusCode = response.response?.statusCode
            if let allHeaderField = response.response {
                allHeaderField.setHeaders()
            }
            switch response.result {
            case .success(let data):
                if statusCode == 200 {
                    success(data as AnyObject)
                } else {
                    failure(NSError.init(domain: "www.wen.com", code: 101010, userInfo: ["message": "Something went wrong. Please trt again."]))
                }
            case .failure(let error):
                failure(error as NSError?)
            }
        })
    }
}

Затем создайте класс обслуживания в соответствии с использованием, как здесь я создаю класс обслуживания профиля для входа в систему и регистрации, а также тип профиля. Все API добавляются в этот класс, так что вы можете создать несколько классов обслуживания в соответствии с использованием:

import Alamofire

///Profile service to call the profile api's
class ProfileService: BaseService {
    /**
     This is request to BaseService to get Login

     - parameter email: User email id
     - parameter password: User password to login
     - parameter success: success response
     - parameter failure: failure response
     */
    func doLogin(email: String, password: String, success: @escaping ((_ response: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
        var request = AlamofireRequestModal()
        request.path = "www.yourpath.com"
        request.parameters = ["email": email as AnyObject,
                              "password": password as AnyObject
                            ]
        callWebServiceAlamofire(request, success: success, failure: failure)
    }
}

Теперь, вы можете вызывать этот метод doLogin службы Profile из любого места, например, Или вы можете создать больше слоев, таких как класс Model, и вызывать этот сервис из класса модели, или Вы можете вызывать напрямую так:

ProfileService().doLogin(email: "Email", password: "Password", success: { (response) in
    // Code here for handle success response
}) { (error) in
    // Code here for handle error
}
0 голосов
/ 08 мая 2018

Используете ли вы Alamofire ?, если да, то у меня есть хороший метод, написанный в NetworkHelper Class.

import Foundation
import Alamofire

open class NetworkHelper {

class var sharedManager: NetworkHelper {
    struct Static{
        static let instance: NetworkHelper = NetworkHelper()
    }
    return Static.instance
}

func request(_ method: HTTPMethod
    , _ URLString: String
    , parameters: [String : AnyObject]? = [:]
    , headers: [String : String]? = [:]
    , onView: UIView?, vc: UIViewController, completion:@escaping (Any?) -> Void
    , failure: @escaping (Error?) -> Void) {

    let URL = BASE_PATH + URLString
    Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
        .responseJSON { response in

            switch response.result {
            case .success:
                completion(response.result.value!)
            case .failure(let error):
                failure(error)
                guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
                    return
                }

            }
    }
}
}
0 голосов
/ 08 мая 2018

В случае использования библиотеки Alamofire я могу предложить использовать

class NetworkManager {
static let shared = NetworkManager()

static let alamofireManager: SessionManager = {
    let sessionConfiguration = URLSessionConfiguration.default
    sessionConfiguration.timeoutIntervalForRequest = TimeInterval(_TIMEOUT)
    sessionConfiguration.timeoutIntervalForResource = TimeInterval(_TIMEOUT)
    return Alamofire.SessionManager(configuration: sessionConfiguration)
}()

func performRequest(url: String,
                    method: HTTPMethod = .get,
                    parameters: [String: Any] = [String: Any](),
                    encoding: ParameterEncoding = URLEncoding.default,
                    contentType: String? = nil,
                    headers: HTTPHeaders = [String: String](),
                    success: @escaping(Data, Int) -> (),
                    failure: @escaping(CustomError) -> ()) {

        debugPrint("NetworkManager is calling endpoint: \(url)")
        NetworkManager.alamofireManager.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).validate().response { response in
            guard let status = response.response?.statusCode, let data = response.data else {
                if let error = response.error {
                    debugPrint("Error when calling endpoint \(url)")
                    failure(.unknownError(message: error.localizedDescription))
                }
                return
            }
            debugPrint("HTTP Status received: \(status)")
            success(data, status)
       }
    } else {
        failure(.noNetworkConnection)
    }
}

Пожалуйста, не стесняйтесь модифицировать обработчик failure с вашей пользовательской ошибкой или чем угодно. Конечно, тогда вам нужно сериализовать ответ.

0 голосов
/ 08 мая 2018

Я бы написал класс сетевого менеджера, который принимает параметры веб-службы, если они есть, в качестве аргументов.

Вот грубый пример архитектуры

class YourNetworkManager {



     public func callSpecificWebService(argument : Type?, [optional closure to handle results]) {

          // Generate the actual URL to be called here. Usually by 
          // appending a suffix to some constant base url 

          // The web service call mechanism goes here.
          // This could either use the NSURLSession API 
          // or some third party library such as Alamofire

          // Process the generic response conditions from the web service  
          // here. Pass on the specific parts to the calling method.
       }
    }

Как я уже говорил, это грубый пример. Чем больше модульности вы можете сделать вещи, тем лучше будет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...