I have this method :
func getdata(someString: String, onComplete: @escaping ((_ someArrayData: [String], _ error: Error?) -> Void)) {
var result: [BanPhone] = []
// Some Actions
if(someaction is successful)
{
onComplete(result)
}
else {
onComplete(result, Error)
}
}
Error is optional i want to pass this parameter only when i get error. else i wanted to send back result. How can i do that over here
In answer to your question, you call it with a result when successful, passing nil
for the error parameter, e.g. in success scenario:
onComplete(result, nil)
And if there was some error, you’d call it supplying the error code, but no value:
onComplete(nil, error)
Better, we would prefer to use Result
type. See https://www.swiftbysundell.com/basics/result/ for practical discussion.
We favor Result
over the “two optional parameters” pattern because it makes it explicit to the caller that either it will be successful with a value or a failure with an error, one or the other, but not both.
func fetchData(with someString: String, completion: @escaping (Result<[String], Error>) -> Void)) {
…
doingSomethingAsynchronous {
…
// if failed
if let error {
completion(.failure(error))
return
}
// if successful
completion(.success(value))
}
}
And use it like so:
fetchData(with: string) { result in
switch result {
case .failure(let error):
print(error)
case .success(let value):
// do something with `value`
}
}
Now, this is how the two optional parameter pattern tends to work in practice (it is one or the other), but Result
formalizes the contract, saves you from unwrapping optionals, etc.
Nowadays, we would use Swift concurrency, which is far simpler:
func fetchData(with someString: String) async throws -> [String] {
…
return try await doingSomethingAsynchronous()
}
So, you would either return
a value or throw
an error.