do-try-catch usage in Swift 2 - xcode

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.

Related

I need help Debugging/Fixing this code, by the way this is in Xcode, I am using the OpenAI Package by adamrushy

I am having an issue, I don't know if it related to the package but it probably is so here is my code. This is the package I used; https://github.com/adamrushy/OpenAISwift
// Send query to OpenAI
openAI.send(prompt: query) { [weak self] (response, error) in
guard let self = self else { return }
if let error = error {
print("Error: \(error.localizedDescription)")
self.startListening()
return
}
if let response = response {
// Use Text to Speech to speak response
let synthesizer = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: response.text)
synthesizer.speak(utterance)
}
By the way the below Bugs are on this line "openAI.send(prompt: query) { [weak self] (response, error) in"
Bug 1: Unable to infer type of closure parameter 'error' in the current context
Bug 2: Unable to infer type of a closure parameter 'response' in the current context
Bug 3: Value of type 'OpenAI' has no member 'send'
I tried removing the error thing itself, it gave more issues. I tried changing 'send' to other things, it just kept giving the same error. And I could not touch 'response' as it is important.

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

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")
}

Xcode 7.0 Swift Update Problems

I'm trying to update my project to work with Xcode 7.0 and after updating my Swift projects I'm getting an error that I don't understand on this line.
let jsonData:NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
The error is
"Call can throw, but it is not marked with 'try' and the error is not handled"
I'm also getting these two errors in my project files...
"linker command failed with exit code 1 (use -v to see invocation)"
and
"error: cannot parse the debug map for "/Users/MattFiler/Library/Developer/Xcode/DerivedData/ePlanner-cqwzlxqgpwaloubjgnzdlomjkfea/Build/Intermediates/SwiftMigration/ePlanner/Products/Debug-iphonesimulator/ePlannerTests.xctest/ePlannerTests": No such file or directory"
Try this code:
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(urlData!, options: .MutableContainers ) as! NSDictionary
// Use jsonData here
} catch {
print("Well something happened: \(error)")
}
You'll need the try keyword as NSJSONSerialization.JSONObjectWithData now throws an error if something failed since Swift 2. Throwing functions need to be marked with try or try!.
Also you'll need the do { ... } catch to catch any errors that may occur. This will catch the error and handle it.
You might want to read up on the changes in Swift 2 to understand why this happened. Also the WWDC videos will be very helpful.
You need to try and catch if it throws an error.
do {
let jsonData:NSDictionary = try NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
//...
}
catch {
}

fatal error: unexpectedly found nil while unwrapping an Optional value in Swift when tried to parse JSON

I've tried to build up a document-based Cocoa app and when I tried to parse JSON in readFromData: ofType: error: method, I got an error: fatal error: unexpectedly found nil while unwrapping an Optional value. The actual line that caused the error is the following:
override func readFromData(data: NSData?, ofType typeName: String?, error outError: NSErrorPointer) -> Bool {
var error: NSErrorPointer!
var loadedDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: error) as? NSDictionary // this causes an error
return true
}
It looks like the NSJSONSerialization.JSONObjectWithData() method caused the error, but why did it issue it?
I changed options: argument to either nil or 0, and also changed error: argument to nil, but nothing solved the issue.
I also ensured that data is not nil.
So what am I missing? I think the JSON method tried to force unwrapping within it, but how can I know that? And how can I escape the fatal error and have my app run properly?
I use Xcode6-beta 3 on Yosemite beta3.
Most likely the problem is that you have data that isn't actually JSON, so the deserialisation will return nil, or the data is an array, and converting it to a dictionary will obviously crash.
You don't seem to understand some of the basics. What do you think AllowFragments is going to achieve? And why did you change error to nil? Do you understand what the error variable is there for? It's there to tell you what errors the JSON parser found. By setting the variable to nil, you prevent it from helping you.
If the data does not contain a valid JSON object, the JSONObjectWithData function will return a nil, so you need to do a conditional unwrapping as follows:
if let dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: jsonError) as? NSDictionary {
println("Dictionary: \(dict)")
} else {
println("nil")
let resultString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Flawed JSON String: \(resultString)")
}
I hope it helps..... e
In this case outError is supplied as an argument so you should use it (I overlooked that).
Looks like this function's purpose is to check whether data is valid JSON.
Then your funciton should be:
override func readFromData(data: NSData?, ofType typeName: String?, error outError: NSErrorPointer) -> Bool {
if let loadedDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: outError) as? NSDictionary {
return true
} else {
return false
}
}
Now this function:
write error to where the caller specified in ourError should error occur
return wheter the data is valid JSON as NSDictionary
FYI I happened to write a JSON handler, too.
https://github.com/dankogai/swift-json/
Which includes NSJSONSerialization.JSONObjectWithData.

Resources