1

I'm attempting to login to my app, however, all my APIRequests are showing as Void instead of APIRequest. This function was working back in Swift 2 and has since gone through some minor changes to attempt to migrate from PromiseKit 4 to PromiseKit 6.

The function does touch a lot of other things, please leave a comment if you need to see more. The function giving me the errors is:

class func recover403(error: Error) -> Promise<NSData> {
        if case let APIError.InvalidToken(request) = error {
            // Log in, then continue the promise chain
            let login = RootViewController.sharedInstance.showLoginController()
            return login.then { request -> Promise<NSData> in
                return API.transmit(request: request as! APIRequest)
            }
        } else if case CocoaError.userActivityConnectionUnavailable = error {

            let vc = ErrorViewController(nibName: "ErrorViewController", bundle: nil)
            let actions = ["Try Again"]

            vc.actions = actions
            vc.promise.then { index -> Promise<NSData> in
                RootViewController.sharedInstance.popAlertViewController()
                return API.transmit(request: request as! APIRequest)
            }.catch({ (Error) in
                // No catch
            })

            RootViewController.sharedInstance.pushAlertViewController(nvc: vc)
            vc.errorLabel.text = "Please check your network connection and try again!"
        }
        return Promise<NSData>(error: error)
    }

'return API.transmit(request: request as! APIRequest)' is throwing

Error: Value of tuple type 'Void' has no member 'value'
Warning: Cast from 'Void' to unrelated type 'APIRequest' always fails

the 2nd 'return API.transmit(request: request as! APIRequest)' is throwing

Error: Generic parameter 'T' could not be inferred
Warning: Cast from '(String, Any?) -> Promise<_>' to unrelated type 'APIRequest' always fails

Here is the APIRequest.swift

import Foundation

class APIRequest: NSMutableURLRequest {

    var errorConditions: [APIRequestErrorCondition] = []

    init(_ path: String, JSON: Any? = nil) {
        let URL = NSURL(string: API.baseURL + path)!
        super.init(url: URL as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60)

        // Settings for both GET and POST
        setValue(API.agent, forHTTPHeaderField: "User-Agent")
        setValue("application/json", forHTTPHeaderField: "Accept")

        // Settings for POST, which is assumed when JSON != nil
        if let JSON = JSON {
            httpMethod = "POST"
            httpBody = try! JSONSerialization.data(withJSONObject: JSON, options: [])
            setValue("application/json", forHTTPHeaderField: "Content-Type")
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

And finally the transmit function:

class func transmit(request: APIRequest) -> Promise<NSData> {
    request.auth()
    return Promise<NSData> { seal in
        let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (_data, _response, _error) in
            if let data = _data {
                seal.fulfill(data as NSData)
            } else if let error = _error {
                if case URLError.badServerResponse = error, let rsp = _response as? HTTPURLResponse {
                    seal.reject(BadUrlError.badResponse(rsp.statusCode))
                } else {
                    seal.reject(error)
                }
            } else {
                seal.reject(PMKError.invalidCallingConvention)
            }
            seal.fulfill(_data! as NSData)
        })
        task.resume()
    }
}

This error touches a lot, so let me know in the comments if there's a section missing that you need to see!

Added: 'request' declaration

class func request<T>(path: String, JSON: Any? = nil) -> Promise<T> {
    let request = APIRequest(path, JSON: JSON)
    request.errorConditions = [API.InvalidTokenCondition, API.BadResponseCodeCondition]
    return API.promise(request: request)
}

Added: 'login' declaration

func showLoginController() -> Promise<Void> {
    if let vc = modalController.vcs.last as? LoginViewController {
        return vc.promise
    }
    let vc = LoginViewController(nibName: "LoginViewController", bundle: nil)
    pushModalViewController(nvc: vc, animated: true)
    return vc.promise
}
Konrad Wright
  • 1,254
  • 11
  • 24
  • 1
    Promises handling looks fine. The only issue seems to be with request objects. You are passing some class level(i think) request object here `APIError.InvalidToken(request)` and `login.then` is also returning a `request` object that you are passing to `API.transmit` method by downcasting to `APIRequest`. You should show the declaration of `request` where `recover403` is declared. And also show the `login.then` declaration as i feel this `promise` is returning a `tuple` but you are forcefully casting to `APIRequest` – Kamran Nov 04 '18 at 05:44
  • That's great insight @Kamran however, I still can't seem to fix the issue.. I was able to silence the unrelated type warning though, however the errors are still prevalent. – Konrad Wright Nov 04 '18 at 10:35
  • 1
    Ok, one issue is that this method `showLoginController()` is returning a `Promise` with no value i.e, `Promise` so when you are trying to downcast `request as! APIRequest`, it is throwing that error `Error: Value of tuple type 'Void' has no member 'value'`. – Kamran Nov 04 '18 at 10:43
  • It makes perfect sense why Promise wouldn't have a member value. I'm just trying to understand and update what the previous developer had in mind with this sending the APIRequest. I have no idea how this worked in the Swift2 version. Any clue as to what the previous dev was trying to accomplish? And to what I could do to update this to its Swift4 equivalent? – Konrad Wright Nov 04 '18 at 10:53
  • @Kamran I did find out a way to silence the first error by changing 'request' to 'req' on the login.then line, however that's probably not the fix for this. (Could be but I'm still relatively a beginner at this.) – Konrad Wright Nov 04 '18 at 10:55
  • 1
    As you are updating to new version. It should be completely convertible but because of deeper chaining you are having tough time. It looks like we will need more code to fix all these compiler issues. May be we can move to chat otherwise it will clutter the comments section. – Kamran Nov 04 '18 at 11:00
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/183072/discussion-between-konrad-wright-and-kamran). – Konrad Wright Nov 04 '18 at 11:09

0 Answers0