I commonly see a pointer to an optional error variable being used, just like in this block of code:
if fileManager.fileExistsAtPath(path)
{
var error: NSError?
if !fileManager.removeItemAtPath(path, error: &error)
{
println("Error removing the file : \(error)")
}
}
Why do we do this?
The error parameter is an inout parameter, and can set the value of error rather than returning it from the function. Look up "inout" in Apple's iBook on Swift.
Related
I used this method very much in Swift 1.2: NSURLConnection.sendSynchronousRequest(:_:_:_) but this is apparently deprecated in iOS9. It still works however but now it uses the new Swift 2.0 Error Handling and I don't know how I will get the error message if it fails, ex. if time runs out.
I know I have to put it into a do-catch and then say try before the metho but I dont know how to catch the error message.
do {
let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: nil)
return data
}
catch _ {
return nil
}
Before I used NSError and then its description property, but now I have no clue.
Use automatic error variable, and you can cast it to NSError if you wish:
catch {
let nsError = error as NSError
print(nsError.localizedDescription)
}
You can now throw any object inheriting ErrorType, and provide custom handling in the catch sentence. You can also cast the error to NSError to access localizedDescription for handling third party errors.
Casting an enum ErrorType will produce a NSError with domain equal to the enum name, code equal to the enum value and an auto-generated localizedDescription with the following format:
The operation couldn’t be completed. (DOMAIN error CODE.)
For example, the following code:
enum AwfulError: ErrorType {
case Bad
case Worse
case Terrible
}
func throwingFunction() throws {
throw AwfulError.Worse
}
do {
try throwingFunction()
}
catch AwfulError.Bad {
print("Bad error")
}
catch let error as NSError {
print(error.localizedDescription)
}
Will print
The operation couldn’t be completed. (AwfulError error 1.)
Despite the question title specifying Swift 2, this answer is for Swift 3.
As #redent84 points out, since Swift 2 an Error object may be a home-made one. Here's a method I wrote to analyze and print the default error object available in a "catch" statement that doesn't specify any specific error type:
// Method to print an unknown Error type object to the system output.
static func printCaughtError(_ unknownError : Error) {
let objectDescription = String(describing: unknownError)
let localizedDescription = unknownError.localizedDescription
if localizedDescription != "" {
if localizedDescription.contains(objectDescription) {
print(localizedDescription)
return
}
if !objectDescription.contains(localizedDescription) {
print(objectDescription + ": " + localizedDescription)
return
}
}
print(objectDescription)
}
Then you can call it like this:
catch {
printCaughtError(error)
}
How to get the error message that is inside userInfo:
let errorMessage = (error as NSError).userInfo["message"] as? String
var error: NSError? = nil
return app.managedObjectContext!.save(&error)
It said "Cannot force unwrap value of non-optional type 'NSManagedObjectContext'"
And if i delete '!'
It said "'&' used with non-in out argument of type '()'"
And finally i delete '&'
It said "Argument passed to call that takes no arguments"
I feel hopeless.
You need to use the new syntax:
do
{
try app.managedObjectContext.save()
} catch let error as NSError {
print(error)
}
I used this method very much in Swift 1.2: NSURLConnection.sendSynchronousRequest(:_:_:_) but this is apparently deprecated in iOS9. It still works however but now it uses the new Swift 2.0 Error Handling and I don't know how I will get the error message if it fails, ex. if time runs out.
I know I have to put it into a do-catch and then say try before the metho but I dont know how to catch the error message.
do {
let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: nil)
return data
}
catch _ {
return nil
}
Before I used NSError and then its description property, but now I have no clue.
Use automatic error variable, and you can cast it to NSError if you wish:
catch {
let nsError = error as NSError
print(nsError.localizedDescription)
}
You can now throw any object inheriting ErrorType, and provide custom handling in the catch sentence. You can also cast the error to NSError to access localizedDescription for handling third party errors.
Casting an enum ErrorType will produce a NSError with domain equal to the enum name, code equal to the enum value and an auto-generated localizedDescription with the following format:
The operation couldn’t be completed. (DOMAIN error CODE.)
For example, the following code:
enum AwfulError: ErrorType {
case Bad
case Worse
case Terrible
}
func throwingFunction() throws {
throw AwfulError.Worse
}
do {
try throwingFunction()
}
catch AwfulError.Bad {
print("Bad error")
}
catch let error as NSError {
print(error.localizedDescription)
}
Will print
The operation couldn’t be completed. (AwfulError error 1.)
Despite the question title specifying Swift 2, this answer is for Swift 3.
As #redent84 points out, since Swift 2 an Error object may be a home-made one. Here's a method I wrote to analyze and print the default error object available in a "catch" statement that doesn't specify any specific error type:
// Method to print an unknown Error type object to the system output.
static func printCaughtError(_ unknownError : Error) {
let objectDescription = String(describing: unknownError)
let localizedDescription = unknownError.localizedDescription
if localizedDescription != "" {
if localizedDescription.contains(objectDescription) {
print(localizedDescription)
return
}
if !objectDescription.contains(localizedDescription) {
print(objectDescription + ": " + localizedDescription)
return
}
}
print(objectDescription)
}
Then you can call it like this:
catch {
printCaughtError(error)
}
How to get the error message that is inside userInfo:
let errorMessage = (error as NSError).userInfo["message"] as? String
I am using CHCSVParser to parse some data. It has been installed through CocoaPods with use_frameworks!. Viewing the header file, there are two functions that I can use, I want to use the one that returns an error to see if something went wrong.
public convenience init!(contentsOfDelimitedURL fileURL: NSURL!, options: CHCSVParserOptions, delimiter: unichar)
// This is the one I want to use as I need the error if it fails.
public convenience init(contentsOfDelimitedURL fileURL: NSURL!, options: CHCSVParserOptions, delimiter: unichar, error: ()) throws
The actual Objective-C methods of the two above:
- (NSArray *)componentsSeparatedByDelimiter:(unichar)delimiter options:(CHCSVParserOptions)options;
- (NSArray *)componentsSeparatedByDelimiter:(unichar)delimiter options:(CHCSVParserOptions)options error:(NSError *__autoreleasing *)error;
I am using the error function like this:
do {
let components = try NSArray(contentsOfDelimitedURL: url, options: CHCSVParserOptions.RecognizesBackslashesAsEscapes, delimiter: 0x002C, error: ())
// Do what ever I need to do...
} catch {
print("Error: \(error)")
}
However I assume passing () to the error param is wrong. When I run this with something I know will fail the catch is never being called. Unsure on how to call this function correctly?
Using Xcode 7 beta 5.
You need to pass the error like this
var error: NSError?
var results = context.executeFetchRequest(request, error: &error)
and also i think you need to check the error object for any error rather than putting try catch
I see many versions of this question, but I've looked through many of them and haven't found something explaining my problem yet. I hope this isn't a repeat question.
I am simply trying to initialize an AVAssetWriter with this init! method defined in the documentation:
init!(URL outputURL: NSURL!,
fileType outputFileType: String!,
error outError: NSErrorPointer)
So I've written the following code in my playground:
var err : NSError? = nil
var outputPath = "\(NSTemporaryDirectory())mypath.mov"
var url = NSURL(fileURLWithPath: outputPath)
var fileManager = NSFileManager.defaultManager()
println("The putput path is \(outputPath)")
if(fileManager.fileExistsAtPath(outputPath))
{
fileManager.removeItemAtPath(outputPath, error: &err)
println(outputPath)
if(err != nil)
{
println("Error: \(err?.localizedDescription)")
}
}
var writeInitErr : NSError? = nil
var assetWriter = AVAssetWriter(URL: url, fileType: AVMediaTypeVideo, error: writeInitErr)
However, the last line throws the error "Extra argument 'URL' in call". None of the solutions I found in other questions about this error seem to apply here. Am I passing the wrong type to the parameter? Am I misunderstanding the use of the initializer?
Well, as is often the case, I figured out the answer minutes after asking the question.
The problem is actually with the "error: writeInitError" parameter, which should be
"error: &writeInitError"
Apparently the xcode error reporting is buggy, and was reporting a problem with the URL parameter instead. Fixing the error parameter solved the problem.
I suppose until the error reporting is improved, "Extra argument in call" translates to "Something is wrong with one of your parameters".