How to pass an Error up the stack trace in Swift
Referring to Swift - Error Handling Documentation, you should:
1- Create your custom error type, by declaring enum which conforms to Error Protocol:
enum CustomError: Error {
case error01
}
2- Declaring foo()
as throwable function:
func foo() throws {
throw CustomError.error01
}
3- Declaring bar()
as throwable function:
func bar() throws {
try foo()
}
Note that although bar()
is throwable (throws
), it does not contain throw
, why? because it calls foo()
(which is also a function that throws an error) with a try
means that the throwing will -implicitly- goes to foo()
.
To make it more clear:
4- Implement test()
function (Do-Catch):
func test() {
do {
try bar()
} catch {
print("\(error) has been caught!")
}
}
5- Calling test()
function:
test() // error01 has been caught!
As you can see, bar()
automatically throws error, which is referring to foo()
function error throwing.
Swift pass error caught inside function
Just write
func anotherMethod() throws {
try someMethod()
}
then the error will be handed over.
Swift 3 - do-catch and throw
If you want to substitute the error thrown by convert()
by another error then call convert()
in a local do/catch context.
The outer do/catch is not needed because
a throwing function "automatically" propagates errors up
to the caller (compare How to pass an Error up the stack trace in Swift).
public func myFunc() throws
{
let obj: Any // or whatever type convert() returns
do {
obj = try convert(param: 42)
} catch {
throw MyError.ConversionFailed
}
// work with obj...
if obj is Array {
// great, continue working with obj...
} else {
throw MyError.NotAnArray
}
}
How to call throw in nested non-throwable closure?
If you can't change the function getOptionalConfigurations then you can't throw from inside function because nothing will process the error that you throw.
But if you want to throw the error from the outer function without changing the existing architecture I can propose only a very bad solution:
func retrieveConfigurations(_ completion:@escaping (([String]?) throws -> Void)) throws {
let d = DispatchGroup()
var errorToThrow: Error?
d.enter()
getOptionalConfigurations { (configurations: [String]?, error: Error?) in
do {
try completion(configurations)
d.leave()
} catch {
errorToThrow = error
d.leave()
}
}
d.wait(timeout: .now() + 10)
if let error = errorToThrow {
throw error
}
}
That's bad because if getOptionalConfigurations
is executed async then current thread will have to wait for it's completion. I also added timeout for 10 seconds. You can change that to infinity which will make it even worse or just change the number of seconds.
inout parameter in Swift
The error should be at the top of the stack trace:
Simultaneous accesses to 0x109fac098, but modification requires exclusive access.
When you pass char1
as a inout
parameter to changeChar
it is a memory violation to access char1
in any other way until that function returns.
For full details, see SE-176 Enforce Exclusive Access to Memory which added this restriction in Swift 4.
Swift return or throw
I don't think you can use null coalesce
in a return statement. However, you can do something like this
guard let res = calcSomething() else { throw err.invalidSomething }
return res
Related Topics
Line-Breaking Widget Layout for Android
How to Parse JSON Array with Gson
Format Float to N Decimal Places
Finish All Previous Activities
How to Connect Remote MySQL Database in Android Using Jdbc
Android Recyclerview Addition & Removal of Items
Any Good Orm Tools for Android Development
Android Studio Google Jar File Causing Gc Overhead Limit Exceeded Error
Change the System Brightness Programmatically
How to Set Addsnapshotlistener and Remove in Populateviewholder in Recyclerview Item
Why Is 08 Not a Valid Integer Literal in Java
Spring Data JPA Deleteby Query Not Working
Find Duplicate Value in Array List and Print the Duplicated Value