-1

I have this code:

enum ApiConstans {
    static let BaseUrl = "http://myname.pl"
    static let iosPath = "/pub/ios/"
    static let jsonPath = "json.php"

    static var fullPath: String { return BaseUrl + iosPath + jsonPath }
}


struct Connect {
    enum Result<T> {
        case succes(T)
        case error(String)
    }

    func getJsonFromServer(parameters: String) -> Result<String> {

        let fullUrlString = ApiConstans.fullPath + parameters
        guard let url = URL(string: fullUrlString) else {
            return .error("Error 100: Problem with url")
        }

        URLSession.shared.dataTask(with: url) {  (data, response, error) in
            guard error == nil else {
                return .error("Error 100: Problem with url")
            }

            guard let data = data else {
                return .error("Error 101: Problem with url")
            }

            debugPrint("R> \(fullUrlString)")
            return .succes(data)
        }
    }

    func checkUsersLogin(login: String?, password: String?) ->  Result<String> {
        getJsonFromServer(parameters: "?action=LOGOWANIE&login=\(login!)&password=\(password!)")
    }

}

I have problem with errors in all return: Type 'Void' has no member 'error' and Type 'Void' has no member 'succes'

could I ask you to repair this code?

Łukasz Betta
  • 131
  • 3
  • 12
  • Please see https://stackoverflow.com/questions/25203556/returning-data-from-async-call-in-swift-function?s=3|62.0655 – rmaddy May 07 '18 at 06:27

3 Answers3

2

The compiler tells you that you return your Result from the async dataTask handler which is not expected to return your custom type.

The main issue of your code is that you perform an async operation (calling the server) in a sync way (immediately returning the result). Instead you should pass a callback closure to getJsonFromServer which you invoke in the dataTask handler.

dr_barto
  • 5,723
  • 3
  • 26
  • 47
2

You should use closure to return data when receive data from server.

typealias completionHandler = (Result<Data >) -> ()

func getJsonFromServer(parameters: String, completion: @escaping completionHandler) {
    let fullUrlString = ApiConstans.fullPath + parameters
    guard let url = URL(string: fullUrlString) else {
        return completion(.error("Error 100: Problem with url"))
    }

    URLSession.shared.dataTask(with: url) {  (data, response, error) in
        guard error == nil else {
            return completion(.error("Error 100: Problem with url"))
        }

        guard let data = data else {
            return completion(.error("Error 101: Problem with url"))
        }

        debugPrint("R> \(fullUrlString)")
        return completion(.succes(data))
    }
}
iParesh
  • 2,338
  • 1
  • 18
  • 30
0

In case of block, the default return type is Void and hence that return is referencing to block return type. You need to use completion handler way to make it work.

enum ApiConstans {
    static let BaseUrl = "http://myname.pl"
    static let iosPath = "/pub/ios/"
    static let jsonPath = "json.php"

    static var fullPath: String { return BaseUrl + iosPath + jsonPath }
}


struct Connect {
    enum Result<T> {
        case succes(T)
        case error(String)
    }

    func getJsonFromServer(parameters: String, completion: @escaping (Result<String>) -> Void) {

        let fullUrlString = ApiConstans.fullPath + parameters
        guard let url = URL(string: fullUrlString) else {
            completion(Result.error("Error 100: Problem with url"))
            return
        }

        URLSession.shared.dataTask(with: url) {  (data, response, error) in
            guard error == nil else {
                completion(Result.error("Error 100: Problem with url"))
                return
            }

            guard let data = data else {
                completion(Result.error("Error 100: Problem with url"))
                return
            }

            print("R> \(fullUrlString)")
            completion(Result.succes("CONVERT DATA TO STRING USE DATA HERE "))
        }
    }

    func checkUsersLogin(login: String?, password: String?, completion: @escaping (Result<String>) -> Void) {
        self.getJsonFromServer(parameters: "?action=LOGOWANIE&login=\(login!)&password=\(password!)", completion: completion)
    }

}

You can pass completion, also you have to wait for API to complete, So i suggest use handler technique for proper flow.

Abhishek Thapliyal
  • 3,497
  • 6
  • 30
  • 69