I have implemented a working multipart upload on iOS using Alamofire. However from time to time an error occurs during the creation of the multipart upload. I would like to handle that error gracefully (currently it calls fatalError and crashes the whole app. I would rather like to do something like throwing and aborting the upload.
Some pseudo code as explanation.
Alamofire.upload(multipartFormData: {data in
if self.create() == .failure {
throw error
},
usingThreshold: UInt64.init(),
to: url,
method: .post,
headers: headers,
encodingCompletion: {error in
self.onEncodingComplete()}
)
Of course this throw does not work, since the closure is not throwing. Does anyone have a working solution for this?
Related
Using Alamofire 4.9.0.
I am trying to implement handling streaming APIs in JSON lines format. Here's how:
stream = Alamofire.request(url, method: HTTPMethod.get,
headers: TTSessionManager.headers)
.validate()
.stream(closure: { (data) in
// parsing JSON lines ...
})
.response(completionHandler: { (response) in
// error handling ...
})
Now the issue is that the first response takes some time to return. And when it does I get a couple of JSON lines in one big batch. After that stream continues to normally respond with a new JSON line per response coming through the stream.
Has anyone encountered this behaviour? I'm wondering wether there is some additional session or request setup needed in order for this to work normal (line per response) from the start. When inspecting the response.metrics after canceling the request a lot of the fields are null so I can't for sure say wether some of the initial connection steps are the issue:
(Domain Lookup Start) (null)
(Domain Lookup End) (null)
(Connect Start) (null)
(Secure Connection Start) (null)
(Secure Connection End) (null)
(Connect End) (null)
So the problem here was that the response header didn't have Content-Type set to application/json. When this header is not set properly, URLSession data task will buffer first 512 bytes of response.
More info can be found here: https://developer.apple.com/forums/thread/64875
I have run into this problem and I cant seem to find any reasonable explanation nor solution.
Just recently I have migrated application from swift 2.3 to swift 3 and then to swift 4.
Today I have noticed that an API call that is returning HTTP status code 200 is interpreted as error in my iOS application. Example of API call:
self.clientApi.post(path: path,
parameters: params as [String : AnyObject]?,
encoding: Alamofire.URLEncoding(),
headers: nil,
success: { (result: ResultType) in
onSuccess()
}, failure: { (error, statusCode) in
onError(error, statusCode)
})
Using fiddler I can see that my API is returning status code 200 after this call, but onError() method is called and so on my application is thinking that request failed.
Error information that I have:
Type: NSError?
domain: "com.alamofirejsontoobjects.error
code: 1
What is not getting through my head is that I don't even use JSONEncoding here, I use URLEncoding because it is call to OAuth endpoint.
Please help.
After reinstalling all pods it has worked like a charm.
Thank you #Nitish
I use Alamofire 4.5.1 to download some mp3 files.
If I provide incorrect URL or the request can't be authorised I get an error with 4xx status code (as it is supposed to be) and in my particular case xml with the error explanation.
The issue is that Alamofire saves the error xml response to my destination url, which looks like: .../my-sound-file.mp3
In other place in my app, which is decoupled from downloading code, I might later check if I have .../my-sound-file.mp3 on disk and try to play it, which obviously fails since my sound file is actually xml file with mp3 extension.
Is there a nicer way to prevent Alamofire saving an error data as an originally requested file?
The code I use (with my crude solution to this issue):
let destination: DownloadRequest.DownloadFileDestination = ...
let request = self.sessionManager.download(url, to: destination)
request.validate()
request.response { response in
if response.error == nil {
// do some stuff
} else {
// So far I am forced to manually remove file in case of error
try? FileManager.default.removeItem(at: destURL)
// propagate error
}
}
I stumbled upon this because I assumed that if a request validation fails the destination URL should be empty.
I think I am not the only one with this assumption: Alamofire: file download and validation failure
Personally, I delete the file in case of error. Just as you propose.
I am a newbie to iOS and using Alamofire in my app. Everything is working fine. Now I want to implement network errors. I have searched about it and here are my findings:
We can implment request timed out in the following way:
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 10
let urlVerifyEmail = ####
manager.request(urlVerifyEmail, method: .post, parameters: ["user_email" : email], encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: { response in
switch response.result {
case .success:
print (“success”)
case .failure(let serverError):
if (serverError._code == NSURLErrorTimedOut)
{
print(”Request timed out”)
}
else
{
print(”Error sending request to server”)
}
}
}
)
I have read there official docs too. However I am not having much clarity.
What does request timed out actually mean? Does it mean that the app is taking too long to send the request? or server is taking too long to send the response back?
What are other types or network errors in Alamofire? What if the connection wasn't successfully made? What if it broke while the request was getting sent? What if it broke while the response was coming back?
If error code for request timed out is -1001 then what are the codes for other network errors? In order to provide the users with the best experience, which is the best approach to cover all of network errors?
I'm using alamorefire to make calls to an API, but I figured that if I put the app in the background, the call will pause and I don't want that. I want it to load and then, when I bring the app to the foreground, I can use the requested data on the UI. How can this be done? At the moment I just do plain requests like this:
Alamofire.request(url, method: .get, parameters: params, headers: header())
.responseJSON{response in switch response.result {
I've tried using the following alamofire configuration:
let configuration = URLSessionConfiguration.background(withIdentifier: "com.cmpny.myapp.background")
let manager = Alamofire.SessionManager(configuration: configuration)
manager.request(url, method: .get, parameters: params, headers: headers())
This gives me the following error:
Request failed with error: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=http://url, NSLocalizedDescription=cancelled, NSErrorFailingURLKey=http://url}
You should use UIBackgroundTaskIdentifier for this purpose.
Apple doc:
https://developer.apple.com/reference/uikit/uiapplication/1623031-beginbackgroundtaskwithexpiratio
Similar question:
https://stackoverflow.com/a/31751337/1689376
Hope this helps ;)