How can I call this Closure in Swift 5 - ios

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!!

Related

Update to Xcode 12: Cannot convert value of type 'DataRequest' to closure result type 'Void'

I am using AlamoFire and PromiseKit to do API calls.
The code was working fine for 2 years until I updated to Xcode 12.0.
Function now returning the error: "Cannot convert value of type 'DataRequest' to closure result type 'Void'"
My function is as follows:
func fetchArticlesFromApi (API: String) -> Promise<[Article]> {
return Promise<[Article]> { seal in
return Alamofire.request(API).validate().responseString(completionHandler: { //Error happening here
response in
switch (response.result) {
case .success(let responseString1):
//Do something
case .failure(let error):
print (error)
seal.reject(error)
}
})
}
}
Error happening in third line of function
Any thoughts what might have changed in this update?
Note: The code works fine when i run the same code on xcode 11.6!
I found the answer for that on Github.
https://github.com/mxcl/PromiseKit/issues/1165
I shouldn't be trying to return anything from the closure passed to Promise.init.
Weird how that was working in previous versions of Xcode.
To fix that I have to replace the return in front of Alamofire.request... with _ =
The function now looks like this:
func fetchArticlesFromApi (API: String) -> Promise<[Article]> {
return Promise<[Article]> { seal in
_ = AF.request(API).validate().responseString(completionHandler: {
response in
switch (response.result) {
case .success(let responseString1):
//Do something
case .failure(let error):
print (error)
seal.reject(error)
}
})
}
}

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#>
}

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

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
...
}

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.

Resources