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?
Alamofire is an HTTP network-based library which is used to handle the web request and response in iOS and MacOS. It is the wrapper class of URLSession and provides an interface on the top of Apple's networking stack.
Alamofire is built on top of NSURLSession, and is less lines of code to do REST interactions with (POST/GET/PUT/etc). It will get you "90%" of the way, but if you need to do super specialized network calls, you will need to use NSURLSession.
Adding Alamofire Into Our Project Launch a new Xcode, SwiftUI based project and add the Alamofire dependency. You can use Cocoapods, Swift Package Manager or Carthage, whichever works the best for you. Once that's done, simply import Alamofire into your Swift class.
And that's it! The Alamofire. framework is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
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")
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With