How to use try with data.withUnsafeBytes() in Swift 5, Swift5? - xcode

If I option click on withUnsafeBytes in my code, the declaration states that the function throws:
func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
When I put in do try catch in my code (see below) I get a warning for the try:
No calls to throwing functions occur within 'try' expression
and a matching warning for the catch:
'catch' block is unreachable because no errors are thrown in 'do' block
Is my code incorrect or is this a problem with Xcode?
func getIntValue(data:Data)->Int
{
var d = -1
do {
d = try data.withUnsafeBytes {
$0.load(as: Int.self)
}
} catch {
return d
}
return d
}
Your input is appreciated.

The throws -> rethrows syntax does the following:
If the code in the closure body contains a throwing function the error is rethrown and you have to add try
If there is no throwing function nothing happens and you must not use try.
In your example the second case occurs so remove try and the do - catch block

Related

ParallelFlux doOnNext how to handle Exception

In my project I have this:
ParallelFlux<Device> flux = Flux.fromIterable(children)
.delayElements(Duration.ofMillis(10))
.parallel(18)
.runOn(Schedulers.elastic(), 10)
.doOnNext(c -> recursiveValidationThroughoutChildren(c, tracker)
});
Where recursiveValidationThroughoutChildren is a method with this declaration:
boolean recursiveValidationThroughoutChildren(Device d, NodeChangesTracker tracker) throws Exception;
What I don't understand is how to handle the exception thrown by this last method. I would like the exception to be propagated outside the ParallelFlux.
Is it possible? What is the correct way to handle it?
I followed the link #Rozart suggested, but I could not apply the solution as it is explained. I had to change it a bit:
ParallelFlux<Device> flux = Flux.fromIterable(children)
.delayElements(Duration.ofMillis(10))
.parallel(18)
.runOn(Schedulers.elastic(), 10)
.doOnNext(child -> {
try {
recursiveValidationThroughoutChildren(child, tracker);
} catch (Exception ex) {
Flux.error(ex);
}
});
The change is needed because the ParallelFlux does not support the "handle" method, so I had to add a try catch and relaunch the exception with a Flux.error.
I don't know if it is good practice, but it is the only way I got it work.

Generic parameter 'Element' could not be inferred?

"Generic parameter 'Element' could not be inferred" - this error comes as I write guard statement - what is inside guard statement which causes error that element could not be inferred.
static func makeTokenForCard(with cardinfo: CardInfo) -> Single<String> {
return Single.create {
single in guard let ck = try CheckoutKit.getInstance("pk_123456789876543234567, env: Environment.SANDBOX, debug: true)
else {
let descr = "Unexpectedly Checkout got invalid private key. You may need to update the app."
single(.error(NSError.recreate(error: CheckoutError.invalidPK as NSError, description: descr)))
return
}
single(.success("123456"))
return Disposables.create()
}
}
When I remove this Guard statement - it returns simple String and errors in Single.
Edit :
After getting more into error, I found that its due to throws.
open class func getInstance(_ pk: String, env: Environment, debug: Bool) throws -> CheckoutKit? {
In Simple Guard & wrapping its fine.
So, How to call a method in Single when it has throws some expected error
?
This isn't RxSwift related but more Swift and handling errors.
The simplest answer to your question is to use try? instead try. This will fix the issue.
You can read more about error handling here https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html

Hide Swift "Will never be executed" warning

I've got some code that is generating warnings like so:
code path.swift:9:13: warning: will never be executed
fatalError()
^
code path.swift:9:13: note: a call to a noreturn function
fatalError()
^
The compiler output doesn't give any -W arguments I can use to silence these in my source file. How can I stop these warnings?
Please note this is testing code and everything is working as designed - removing the lines complained about is not a solution
The Swift compiler does not have an option to suppress warnings
(as far as I know). The only chance is to avoid the warnings.
In your particular case I don't have a full explanation
for the warning, but a possible workaround. As you said in the comments,
the problem occurs with the Nimble framework in
expect{ fatalError() }.to(throwError()) // Warning: Will never be executed
Here, { fatalError() } is a closure of type () -> Void,
and expect ultimately calls the Expression initializer
public init(expression: () throws -> T?, location: SourceLocation, isClosure: Bool = true)
which takes a closure of type () throws -> T? as the first parameter.
The problem is now related to the optional return type T?.
This can be stripped down to the following minimal self-contained example:
let cl1 : () -> Void = { fatalError() } // No warning
let cl2 : () -> Void? = { fatalError() } // Warning: Will never be executed
Only the second line generates a warning.
I assume that the compiler creates some wrapper code to convert
the Void return type from fatalError() to Void?, and then warns
that the wrapper code is never executed.
As a workaround, you can make the closure type explicit as
let cl3 : () -> Void? = { _ -> Void in fatalError() } // No warning
or assign the closure to an intermediate variable:
let fatalClosure = { fatalError() }
let cl4 : () -> Void? = fatalClosure // No warning
This can be applied to your case:
expect {
_ -> Void in fatalError()
}.to(throwError())
But note that fatalError() – when called – terminates the program
immediately. There is no chance to "catch" that termination.

Swift 2.0 Errors thrown from here are not handled

Updating to 2.0 with Xcode 7 Beta 4
I have this code block
do
{
try AVAudioSession.sharedInstance().setActive(true)
} catch let err as NSError
{
println("Dim background error")
}
And its giving me the error (on the try line)
Errors thrown from here are not handled.
Is this a compiler error or is there something I am missing in my syntax?
I checked the docs and my code 'looks' correct.
What types of errors can AVAudioSession.sharedInstance().setActive(true) throw?
If it can only throw NSErrors, then there's no need of specifying this when catching the error. You could simply write:
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Dim background error")
}
If you want to use the error in your catch-scope, you can still access it. Swift automatically binds the thrown error to error, which can be used:
catch {
// do something with `error`
}
If the method throws multiple types of errors, and you only want to deal with the ones that are NSErrors, you can conditionally bind them:
catch let specialError as NSError {
// do something with `specialError`
}
You must ensure though, that every thrown error is handled. So assuming that the method can also throw a RandomError (which I just made up now), you would have to write:
catch let randomError as RandomError {
// do something with `randomError`
}
...in addition to the catch of the NSError.
Or you could of course use the general case:
catch {
// do something with `error`
}
So I assume your problem can be solved by removing let err as NSError, from your catch-statement.
May be a compiler bug. Anyway try removing let err as NSError ; catch alone is enough if you want to catch all errors.
Also, with Swift 2 you should use print, not println.
The following code compiles without errors with XCode 7 Beta 4:
import AVFoundation
class X {
func y() {
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Dim background error \(error)")
}
}
}
check this code that will you get idea on try/catch :
enum ErrorMessages :ErrorType {
case ErrorDescription
}
do
{
try AVAudioSession.sharedInstance().setActive(true)
} catch ErrorMessages.ErrorDescription
{
println("Present the error description here")
}

do-try-catch usage in Swift 2

Is this usage not correct? why? The file name I use is correct!
on the right side of the playground I would aspect to see the content of the txt file.
In terms of why this failed, you'd have to look at the error object and examine why it failed. You're catching the error, so look at it:
func read(path: String) throws {
do {
try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
} catch {
print("cannot read: \(error)")
}
}
That will tell you why it failed.
Having said all of that, this doesn't quite make sense: First, you're reading the contents of the path into the NSString, but discarding it. You presumably want to return this string or do something with it.
Second, read has been declared in such a way as to say that it throws error, but it doesn't really. It catches any error that might happen itself, but doesn't throw anything. You have to decide whether read will throw any errors it generates, or whether it will handle them without throwing any error, or both.
Assuming the caller was going to handle the error, you might just forego any do-try-catch construct in read altogether:
func read(path: String) throws -> NSString? {
return try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
}
Then you can let the caller catch any error that NSString threw. For example, you might catch the "not found" error:
do {
let string = try read(path)
// do something with string
} catch let error as NSError where error.domain == NSCocoaErrorDomain && error.code == NSCocoaError.FileReadNoSuchFileError.rawValue {
// not found handling here
} catch {
print(error)
}
If you really wanted read to not only catch the error, but also make sure it throws one as well, then you'd need to have to explicitly throw an error from its catch block. You can use this pattern using either your own ErrorType or just throwing the original error you just caught:
func read(path: String) throws -> NSString? {
var string: NSString?
do {
string = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
} catch {
// do whatever special handling you want here
// but also throw error so caller is informed that there was an issue
throw error
}
return string
}
Frankly, I think the pattern outlined above is simpler, but given your code snippet, I thought I'd also illustrate this latter pattern, too, in case you needed something like that.
I am also learning, so I wrote a little demo. Hope it helps.

Resources