ov1d1u
ov1d1u

Reputation: 1077

Deciding object type in an if-else block

Given the following code:

for (id object in anArray){
    if ([object isKindOfClass:[ClassOne class]]){
       ClassOne *myObj = [[ClassOne alloc] init];
    }else if ([object isKindOfClass:[ClassTwo class]]){
       ClassTwo *myObj = [[ClassTwo alloc] init];
    }
    myObj.property = TRUE;
}

the compiler will raise an error regarding myObj (undeclared identifier), which is somehow obvious ("what should I do if both conditions will be false?"). That means I have to define the object before the if-else block, but which type of object I have to use? If I use id there will be errors on myObj.property = TRUE;, if I use ClassOne or ClassTwo there will be some warnings regarding incompatible pointer assignment. Should I use some other way instead of the given code?

Thank you.

(note: the snippet was written without using syntax checking or testing it, so it may contains errors)

Upvotes: 0

Views: 100

Answers (5)

Pedro Mancheno
Pedro Mancheno

Reputation: 5237

How about a protocol?

@protocol MyProtocol

@property (assign, nonatomic) BOOL myProperty;

@end

Then:

for (id anObject in anArray){
    if ([anObject conformsToProtocol:@protocol(MyProtocol)]) {
        Class clazz = [anObject class];
        id<MyProtocol>  myObject = [[clazz alloc] init];
        myObject.myProperty = YES;
    }
}

This is the cleanest and shortest solution I can think of. You won't need to cast, instead you will harness the power of objective-c's dynamic binding. You won't have to add too many if-else statements. Instead you just make sure the object that comes in, conforms to your protocol.

Upvotes: 2

graver
graver

Reputation: 15213

It depends on the situation. For example why do you need myObj outside the if-else statement? If you need to pass it to another method you can create a base class, for ex ClassBase and make ClassOne and ClassTwo to inherit from ClassBase and then make your method accept ClassBase as an argument (that's of course if both objects have something in common). If that's not the case, what's the problem to do your logic in every statement:

if ([object isKindOfClass:[ClassOne class]]){
       ClassOne *myObj = [[ClassOne alloc] init];
       myObj.property = YES;
       [self doSomethingWith:myObj];
 }else if ([object isKindOfClass:[ClassTwo class]]){
       ClassTwo *myObj = [[ClassTwo alloc] init];
       myObj.otherProperty = YES;
       [self doSomethingElseWith:myObj];
    }
//end of method

Upvotes: 0

Paresh Navadiya
Paresh Navadiya

Reputation: 38239

As scope of myObj limit to if block so use in if block only. Now if myObj defined outside of if block then object can't have same name.

for (id object in anArray){
 if ([object isKindOfClass:[ClassOne class]]){
   ClassOne *myObj = [[ClassOne alloc] init];
   myObj.property = TRUE;
 }else if ([object isKindOfClass:[ClassTwo class]]){
   ClassTwo *myObj = [[ClassTwo alloc] init];
   myObj.property = TRUE;
 }
}

Upvotes: 0

deleted_user
deleted_user

Reputation: 3805

for (id object in anArray){
    if ([object isKindOfClass:[ClassOne class]]){
        ClassOne *myObj = [[ClassOne alloc] init];
        myObj.property = TRUE;
    }
    else if ([object isKindOfClass:[ClassTwo class]]){
        ClassTwo *myObj = [[ClassTwo alloc] init];
        myObj.property = TRUE;
    }

}

Upvotes: -1

E. L&#252;ders
E. L&#252;ders

Reputation: 1495

You can use id to init your classes and cast them later to the correct custom class before setting the .property = TRUE

for (id object in anArray){
    id myObj;
    if ([object isKindOfClass:[ClassOne class]]){
        myObj = [[ClassOne alloc] init];
    }else if ([object isKindOfClass:[ClassTwo class]]){
        myObj = [[ClassTwo alloc] init];
    }

    if ([object isKindOfClass:[ClassOne class]]){
        ((ClassOne *)myObj).property = TRUE;
    }else if ([object isKindOfClass:[ClassTwo class]]){
        ((ClassTwo *)myObj).property = FALSE; // or whatever
    }
}

Upvotes: 1

Related Questions