tqn
tqn

Reputation: 125

Use generic type and cast to other class type in Swift

I am a new iOS developer. Based on my experience in android development, I am trying to write api class, request and auto parse json based on type input use HandyJSON library, something like

static func request<T: NSObject>(_ urlRequest: URLRequestConvertible, doOnSuccess: @escaping (T)-> Void, doOnError: @escaping (Error)-> Void) {
    Alamofire.request(urlRequest).responseJSON(completionHandler: { response
        in
            if (T is BaseResponse) {  // This is Invalid Swift code

                // I am using HandyJSON Library to parse to T
                if let jsonObject = (T as! BaseResponse).deserialize(from: response.result.value as? NSDictionary) {
                    doOnSuccess(jsonObject)
                }
            }
            else {
                doOnError(NSError.init(domain: APIRouter.DOMAIN, code: APIRouter.ERROR_INTERNAL_ERROR, userInfo: nil))
            }
        }
    })
}

There're part in this code are invalid in Swift and I couldn't search any solution for that.

Also it's welcome if you have any suggestion for my api request function. I'm so surprise that in my project, they don't parse json and access value based on key, also use some json parser library like HandyJSON is not popular.

Upvotes: 1

Views: 570

Answers (1)

Mukesh
Mukesh

Reputation: 2902

If you want to create Generic method which can return BaseResponse and also Array< BaseResponse > then you should create two methods like:

static func request<T: BaseResponse>(_ urlRequest: URLRequestConvertible, doOnSuccess: @escaping (T)-> Void, doOnError: @escaping (Error)-> Void) {
    Alamofire.request(urlRequest).responseJSON(completionHandler: { response
        in
            if let jsonObject = T.deserialize(from: response.result.value as? NSDictionary) {
                doOnSuccess(jsonObject)
            } else {
                doOnError(NSError.init(domain: APIRouter.DOMAIN, code: APIRouter.ERROR_INTERNAL_ERROR, userInfo: nil))
            }
    })
}

static func request<T: BaseResponse>(_ urlRequest: URLRequestConvertible, doOnSuccess: @escaping ([T])-> Void, doOnError: @escaping (Error)-> Void) {
    Alamofire.request(urlRequest).responseJSON(completionHandler: { response
        in
            if let jsonObject = [T].deserialize(from: response.result.value as? NSDictionary) {
                doOnSuccess(jsonObject)
            } else {
                doOnError(NSError.init(domain: APIRouter.DOMAIN, code: APIRouter.ERROR_INTERNAL_ERROR, userInfo: nil))
            }
    })
}

You can also move the Alamofire code to a different method and return Dictionary from it and do the parsing in individual methods.

Upvotes: 1

Related Questions