Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

How would you refactor this kind of code? I've unsuccessfully tried several approaches (NSArray, NSPointerArray, plain C array), but always ran into pointer type checking error.

NSError *error1;
NSError *error2;
NSError *error3;
//imagine MANY of them
[object1 methodWithError: &error1];
[object2 methodWithError: &error2];
[object3 methodWithError: &error3];
BOOL wasErrorOfCode1 = ([error1 code] == 1) || ([error2 code] == 1) || ([error3 code] == 1);
if (wasErrorOfCode1) {
//do stuff
share|improve this question
    
With only three items, I wouldn't refactor it at all. With more items, I would put my errors in an array and iterate over them. –  dasblinkenlight Dec 8 '12 at 14:21
    
I clarified my question (there can by many errors), but as I wrote - I could not get the array thing working because compiler (w ARC) would complain when passing pointer address (&) stored in array to method. I finally got it working with __autoreleasing variable though. Could you please take a look at my suggested solution? –  Ivan Trančík Dec 8 '12 at 23:11
1  
@IvanTrančík When you have vars named error1, error2 and error3, using an array should always be the first step. In Obj-C, always try to use NSArray first before C arrays. –  Sulthan Dec 11 '12 at 11:13
add comment

2 Answers 2

up vote 1 down vote accepted

I want to propose a differently structured code, that especially will be easier to adapt for more objects.

NSArray *objects = @[object1, object2, object3];
NSMutableArray *errors = [NSMutableArray array];

[objects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSError *error;
    [obj methodWithError: &error];
    if(error){
        [errors addObject: @{@"error":error,@"object":obj}];
    }
}];

Now you can iterate over all errors and examine them along with the object the error occurred on.

[errors enumerateObjectsUsingBlock:^(NSDictionary *errorDict, NSUInteger idx, BOOL *stop) {
    NSError *error = errorDict[@"error"];
    id object = errorDict[@"object"];
    if(…){
        //add an appropriate test
    }
}];

you can't add the errors into an array upfront, as

NSError *error1;

will result into a nil-object for the variable error1. NS(Mutable)Arrays can't handle nil objects. Same for dictionaries.
On the other hand my solution allows adding the errors, as it only add them once an existing objects is assigned to the variable error.

share|improve this answer
1  
I like this approach, because it nicely solves the problem. Of course, there is no need for upfront allocation of error pointers for every object - as you correctly stated, it suffices to store only those errors that occurred. –  Ivan Trančík Dec 10 '12 at 12:03
add comment

I found a solution using plain C array and __autoreleasing

int number = 3;
NSError __autoreleasing *errors[number]; //without __autoreleasing, compiler (with ARC) will complain
//imagine MANY of them
[object1 methodWithError: &errors[0]];
[object2 methodWithError: &errors[1]];
[object3 methodWithError: &errors[2]];
BOOL wasErrorOfCode1 = NO;
for (int i = 0; i < number; ++i) {
    wasErrorOfCode1 &= ([errors[i] code] == 1);
}
if (wasErrorOfCode1) {
//do stuff
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.