How can I use NSError in my iPhone App?

后端 未结 9 1087
Happy的楠姐
Happy的楠姐 2020-12-07 06:32

I am working on catching errors in my app, and I am looking into using NSError. I am slightly confused about how to use it, and how to populate it.

相关标签:
9条回答
  • 2020-12-07 07:07

    I'll try summarize the great answer by Alex and the jlmendezbonini's point, adding a modification that will make everything ARC compatible (so far it's not since ARC will complain since you should return id, which means "any object", but BOOL is not an object type).

    - (BOOL) endWorldHunger:(id)largeAmountsOfMonies error:(NSError**)error {
        // begin feeding the world's children...
        // it's all going well until....
        if (ohNoImOutOfMonies) {
            // sad, we can't solve world hunger, but we can let people know what went wrong!
            // init dictionary to be used to populate error object
            NSMutableDictionary* details = [NSMutableDictionary dictionary];
            [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey];
            // populate the error object with the details
            if (error != NULL) {
                 // populate the error object with the details
                 *error = [NSError errorWithDomain:@"world" code:200 userInfo:details];
            }
            // we couldn't feed the world's children...return nil..sniffle...sniffle
            return NO;
        }
        // wohoo! We fed the world's children. The world is now in lots of debt. But who cares? 
        return YES;
    }
    

    Now instead of checking for the return value of our method call, we check whether error is still nil. If it's not we have a problem.

    // initialize NSError object
    NSError* error = nil;
    // try to feed the world
    BOOL success = [self endWorldHunger:smallAmountsOfMonies error:&error];
    if (!success) {
       // inspect error
       NSLog(@"%@", [error localizedDescription]);
    }
    // otherwise the world has been fed. Wow, your code must rock.
    
    0 讨论(0)
  • 2020-12-07 07:07

    Well it's a little bit out of question scope but in case you don't have an option for NSError you can always display the Low level error:

     NSLog(@"Error = %@ ",[NSString stringWithUTF8String:strerror(errno)]);
    
    0 讨论(0)
  • 2020-12-07 07:12
    extension NSError {
        static func defaultError() -> NSError {
            return NSError(domain: "com.app.error.domain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Something went wrong."])
        }
    }
    

    which I can use NSError.defaultError() whenever I don't have valid error object.

    let error = NSError.defaultError()
    print(error.localizedDescription) //Something went wrong.
    
    0 讨论(0)
  • 2020-12-07 07:13

    Another design pattern that I have seen involves using blocks, which is especially useful when a method is being run asynchronously.

    Say we have the following error codes defined:

    typedef NS_ENUM(NSInteger, MyErrorCodes) {
        MyErrorCodesEmptyString = 500,
        MyErrorCodesInvalidURL,
        MyErrorCodesUnableToReachHost,
    };
    

    You would define your method that can raise an error like so:

    - (void)getContentsOfURL:(NSString *)path success:(void(^)(NSString *html))success failure:(void(^)(NSError *error))failure {
        if (path.length == 0) {
            if (failure) {
                failure([NSError errorWithDomain:@"com.example" code:MyErrorCodesEmptyString userInfo:nil]);
            }
            return;
        }
    
        NSString *htmlContents = @"";
    
        // Exercise for the reader: get the contents at that URL or raise another error.
    
        if (success) {
            success(htmlContents);
        }
    }
    

    And then when you call it, you don't need to worry about declaring the NSError object (code completion will do it for you), or checking the returning value. You can just supply two blocks: one that will get called when there is an exception, and one that gets called when it succeeds:

    [self getContentsOfURL:@"http://google.com" success:^(NSString *html) {
        NSLog(@"Contents: %@", html);
    } failure:^(NSError *error) {
        NSLog(@"Failed to get contents: %@", error);
        if (error.code == MyErrorCodesEmptyString) { // make sure to check the domain too
            NSLog(@"You must provide a non-empty string");
        }
    }];
    
    0 讨论(0)
  • 2020-12-07 07:14

    Please refer following tutorial

    i hope it will helpful for you but prior you have to read documentation of NSError

    This is very interesting link i found recently ErrorHandling

    0 讨论(0)
  • 2020-12-07 07:21

    Well, what I usually do is have my methods that could error-out at runtime take a reference to a NSError pointer. If something does indeed go wrong in that method, I can populate the NSError reference with error data and return nil from the method.

    Example:

    - (id) endWorldHunger:(id)largeAmountsOfMonies error:(NSError**)error {
        // begin feeding the world's children...
        // it's all going well until....
        if (ohNoImOutOfMonies) {
            // sad, we can't solve world hunger, but we can let people know what went wrong!
            // init dictionary to be used to populate error object
            NSMutableDictionary* details = [NSMutableDictionary dictionary];
            [details setValue:@"ran out of money" forKey:NSLocalizedDescriptionKey];
            // populate the error object with the details
            *error = [NSError errorWithDomain:@"world" code:200 userInfo:details];
            // we couldn't feed the world's children...return nil..sniffle...sniffle
            return nil;
        }
        // wohoo! We fed the world's children. The world is now in lots of debt. But who cares? 
        return YES;
    }
    

    We can then use the method like this. Don't even bother to inspect the error object unless the method returns nil:

    // initialize NSError object
    NSError* error = nil;
    // try to feed the world
    id yayOrNay = [self endWorldHunger:smallAmountsOfMonies error:&error];
    if (!yayOrNay) {
       // inspect error
       NSLog(@"%@", [error localizedDescription]);
    }
    // otherwise the world has been fed. Wow, your code must rock.
    

    We were able to access the error's localizedDescription because we set a value for NSLocalizedDescriptionKey.

    The best place for more information is Apple's documentation. It really is good.

    There is also a nice, simple tutorial on Cocoa Is My Girlfriend.

    0 讨论(0)
提交回复
热议问题