How can I access Success/Failure cases from this struct? - ios

Using Alamofire v4.0, Alamofire.upload() using MultipartFormData has changed, but I can't find out how to get the success/error case with the enumeration returned in the closure (type is SessionManager.MultipartFormDataEncodingResult)
Looking into the SessionManager.MultipartFormDataEncodingResult struct, here is what I get:
public enum MultipartFormDataEncodingResult {
case success(request: UploadRequest, streamingFromDisk: Bool, streamFileURL: URL?)
case failure(Error)
}

So Xcode seems to have been super unhelpful here and autocompleted the initialiser for that enum rather than the case statement. You would want to do something similar to what you have for the .failure case:
switch encodingResult {
case .success(let request, let streamingFromDisk, let streamFileURL):
// you can now access request, streamingFromDisk and streamFileURL in this scope
...
case .failure(let errorType):
// you can now access errorType in this scope
...
}

Related

How can I call this Closure in Swift 5

I'm still new in Swift development and I'm wondering how can I call This function with the status and results?
func getStatus(completion: #escaping (Swift.Result<SubscriptionStatus, MAPIError>) -> Void )
{
getStatus { result in
switch(result) {
case .success(let subscription):
switch(subscription.status) {
case .subscribed:
completion(.success(true))
default:
completion(.success(false))
}
case .failure(let error):
completion(.failure(error))
}
}
}
Many Thanks
Calling the function
Result is an enum which can be either:
success
or
failure
So, completion(.success(value)) or completion(.failure(someError))
Result is such a powerful keyword in swift!
It determines wether the task should succeed or fail.
To complete your function you should call it like this:
completion(.success(SubscriptionStatusValue))
If the task succeed
Or
Completion(.failure(error))
To call your function you should do it like this:
self.getStatus { result in
switch result {
case .success(let value):
/// do something with value
case .failure(let error):
///handle error
Hope it helps!!

Handling errors properly in swift

I am trying to learn swift and I have hit a wall... I want to be able to switch the type of error i get back so I can do different things. It works fine in the .success but not in the .failure
exporter.export(progressHandler: { (progress) in
print(progress)
}, completionHandler: { result in
switch result {
case .success(let status):
switch status {
case .completed:
break
default:
break
}
break
case .failure(let error):
// I want to check what the error is
// e.g. the debugger says its "cancelled"
break
}
})
}
Can somebody help me with this?
Thanks
If you just want to see what happened, print the error object's localizedDescription.
print(error.localizedDescription)
If you have a decision to make, cast to NSError and examine the domain and code. That is more reliable though not as user-friendly. Only actual testing will tell you what the possible values are.
let error = error as NSError
if error.domain == ... && error.code == ... {
You can work out the corresponding Swift Error type by looking in the FoundationErrors.h header file. Once you do, you can refine your case structure to filter the error type into its own case:
case .failure(let error as NextLevelSessionExporterError):
// do something
case .failure(let error):
// do something else

Display user friendly message for json serialisation error

Iam working on an ios application which uses Alamofire for networking. Some times i get json serialization error. I need to display some user friendly messsage when this error comes. How can I do this by checking Nserror code.
Any help will be appreciated.
If your response gives serialization error then you can get status isFailure You can display some custom message or can user response.result.error object.
Alamofire.request(url, method: .post, parameters: param, encoding: URLEncoding.httpBody, headers: nil).responseSwiftyJSON { (response) in
if response.result.isSuccess {
// Handle your json
} else {
// display message Something went Wrong
}
}
You can actually check AFError.swift file to get familiar with possible values.
switch responseJson.result.error as? AFError{
case .responseSerializationFailed(let reason)?:
switch reason {
case .inputDataNil:
break
case .inputDataNilOrZeroLength:
break
case .inputFileNil:
break
case .inputFileReadFailed(let at):
break
case .stringSerializationFailed(let encoding):
break
case .jsonSerializationFailed(let error): break
***////// DO What ever you want here //////////////////***
case .propertyListSerializationFailed(let error):
break
}
case .some(.multipartEncodingFailed(let reason)):
break
case .some(.responseValidationFailed(let reason)):
break
case .some(.responseSerializationFailed(let reason)):
break
case .none:
<#code#>
case .some(.invalidURL(let url)):
<#code#>
}

Cannot convert value of type '(_, _, _) -> ()' to expected argument type 'Int64'

upload(urlRequest.1, with: urlRequest.0)
Progress {(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in // Error Comes Here
print("\(Int64(totalBytesWritten)) / \(Int64(totalBytesExpectedToWrite))")
}
.responseJSON
{
response in
hideLoading()
showToast("Profile Updated Successfully!!")
}
The problem is that you've replaced .uploadProgress with Progress, but have not changed the three parameters to the closure to be the single Progress parameter.
When you call .uploadProgress, the first parameter to that closure is a Progress (formerly known as NSProgress). But the Alamofire method name, uploadProgress, is unchanged. Only the parameters to the closure have changed.
Thus you want something like:
Alamofire.upload(data, with: request)
.uploadProgress { progress in
print(progress.fractionCompleted)
}
.responseJSON { response in
self.hideLoading()
switch response.result {
case .failure(let error):
self.showToast("Problem uploading: \(error.localizedDescription)")
case .success:
self.showToast("Profile Updated Successfully!!")
}
}
Bottom line, the upload progress method is called uploadProgress, and it takes one parameter, a NSProgress/Progress object.

409 is success in Alamofire?

Strange thing happened to me while implementing networking based on Alamofire. So, my backend can return me 409 and when I get it I want to react properly, so I went for a regular solution:
Alamofire.request(someRequest).responseJSON { response in
switch response.result {
case .Success(let value):
// I get 409 here...
if response.response?.statusCode == 409 {
// ...
}
case .Failure(let error):
// While it should be here...
}
}
Why is it happening? Is it some sort of backend issue or what? I can only thing of one explanation: Request completed, so it's .Success even though you got 409, but this explanation doesn't convince me 😅
HTTP 4.xx class of status codes are intended for situations in which the client seems to have erred, so in normal cases you are to show some kind of error message to the user when it was generated by the server.
In Alamofire world, you can tap into .validate() method if you want response to generate an error if it had an unacceptable status code:
Alamofire.request(someRequest)
.validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .Success(let value):
...
case .Failure(let error):
// You'll handle HTTP 409 error here...
}
}

Resources