Networking with Alamofire on WatchOS

Viewed 1980

I am building an app extension for WatchOS and I want to do some URL requests in the Watch app. I am using Alamofire for the networking part.

Whenever I do a simple request, I am getting these errors in both the simulator as well as on the real device: load failed with error Error Domain=NSURLErrorDomain Code=-2000 "can’t load from network"

It's unclear to me why this happens. The watch is paired with the phone. Using Charles Proxy I can see that the requests were not sent over the network, so it fails before even sending it.

Any ideas are welcome.

EDIT Here is a working extraction of my Communications class:

import Foundation
import Alamofire

class Communication {
    internal lazy var manager = Communication.getSessionManager()

    typealias SuccesBlock = (DataResponse<Any>?) -> ()
    typealias FailureBlock = (DataResponse<Any>?, Error) -> ()
    typealias ProgressBlock = (Progress) -> ()

    internal static var serverTrustPolicyManager: ServerTrustPolicyManager {
        get {
            return ServerTrustPolicyManager(policies: [:])
        }
    }

    static func getSessionManager(_ serializeRequest:Bool = false) -> Alamofire.SessionManager {
        let manager = Alamofire.SessionManager(configuration: URLSessionConfiguration.default, delegate: Alamofire.SessionManager.default.delegate, serverTrustPolicyManager: serverTrustPolicyManager)
        return manager
    }

    static var httpHeaders: HTTPHeaders {
        get {
            var httpHeaders = HTTPHeaders()
            httpHeaders["Accept"] = "application/json"
            return httpHeaders
        }
    }

    func get(_ url: URL, parameters: [String: Any]?, success: @escaping SuccesBlock, failure: @escaping FailureBlock) {
        manager.request(url, method: HTTPMethod.get, parameters: parameters, encoding: URLEncoding.default, headers: Communication.httpHeaders).validate().responseJSON { [weak self] (response) in
            self?.handle(response, success: success, failure: failure)
        }
    }

    internal func handle(_ response: DataResponse<Any>, success: @escaping SuccesBlock, failure: @escaping FailureBlock) {
        switch response.result {
        case .success:
            DispatchQueue.main.async {
                success(response)
            }
        case .failure(let error):
            DispatchQueue.main.async {
                failure(response, error)
            }
        }
    }
}

Anything I send to the get(_ url: URL, parameters: [String: Any]?, success: @escaping SuccesBlock, failure: @escaping FailureBlock) function is giving the -2000 error. The .responseJSON code block is never executed.

EDIT 2

The complete error I am getting is the following:

`2018-09-20 12:12:48.006544+0100 My App Watch Extension[61347:2465172] Task <F80A9AD4-519B-424C-868A-8E239C949016>.<7> load failed with error Error Domain=NSURLErrorDomain Code=-2000 "can’t load from network" UserInfo={NSLocalizedDescription=can’t load from network, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <F80A9AD4-519B-424C-868A-8E239C949016>.<7>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <F80A9AD4-519B-424C-868A-8E239C949016>.<7>"
), NSErrorFailingURLStringKey=https://my.request.url, _kCFNetworkErrorConditionalRequestKey=<CFMutableURLRequest 0x78f37a70 [0x201628c]> {url = https://my.request.url, cs = 0x0}, _kCFNetworkErrorCachedResponseKey=<CFCachedURLResponse 0x7b3d7f20 [0x201628c]>, NSUnderlyingError=0x7b436380 {Error Domain=kCFErrorDomainCFNetwork Code=-2000 "(null)" UserInfo={_kCFNetworkErrorCachedResponseKey=<CFCachedURLResponse 0x7b3d7f20 [0x201628c]>, _kCFNetworkErrorConditionalRequestKey=<CFMutableURLRequest 0x78f37a70 [0x201628c]> {url = https://my.request.url, cs = 0x0}}}, NSErrorFailingURLKey=https://my.request.url} [-2000]`

After getting this error in the console I can now see the request is still sent and succeeds. I assumed this wasn't the case after seeing this error, but I now see that after some delay the request works as expected.

So in the end the app will work, however, the question that remains is: Why do I get this error and how can I get rid of it?

1 Answers

The error description is

NSURLErrorCannotLoadFromNetwork

This error is sent when the task needs to load from the network, but is blocked from doing so by the “load only from cache” directive.

You can solve it by setting the requestCachePolicy of the Alamofire request, like this i.e.:

class RequestManager {

    let manager: SessionManager = {
        let configuration = URLSessionConfiguration.default
        configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
        return SessionManager(configuration: configuration)
    }()

    func fetch() {

       manager.request("https://www.bla.blub") 

       ...
Related