joostevilghost
joostevilghost

Reputation: 149

Initializing object in if condition

I want to create a object but the type depends on the result of the if-condition:

if ([type isEqualToString:@"day"]) {
    GraphDayView *graphv = [[GraphDayView alloc] initWithFrame:rect];
} else {
    GraphMonthView *graphv = [[GraphMonthView alloc] initWithFrame:rect];
}

The problem is that graphv is out of scope, so I am not able to use it after the if-statement. So I tried to declare it as an id:

id graphv;

if ([type isEqualToString:@"day"]) {
    graphv = [[GraphDayView alloc] initWithFrame:rect];
} else {
    graphv = [[GraphMonthView alloc] initWithFrame:rect];
}

But the problem now is, that the compiler doesn't know what kind of object grapv is. So:

graphv.backgroundColor = [UIColor whiteColor];

gives an error. Anyone an idea how to solve this one?

Upvotes: 0

Views: 203

Answers (4)

Hermann Klecker
Hermann Klecker

Reputation: 14068

A lot of suggestions for a common superclass have been made which are most liekly suitable.

In the event they are not then you could use typcasts. However, typecasts may cause exceptions like unknown selecor or bad_exec. If you want to savely use typcasts then you should always check either isKindOfClass or respondsToSelector.

Sample:

id someClassObject; //or any other common superclass* instead of id

If ([something isTrue]) someClassObject = [[AClass alloc] init]; //assuming ARC. If not then you may want to retain/autorelease here too. else someClassObject = [[AClass alloc] init];

... //some code

if ([someClassObject isKindOfClass:[AClass class]]) [(AClass *) someClassObject methodOfAClass];

// if ([someClassObject isKindOfClass:[AClass class]]) { AClass *aClassTemp = (AClass *) someClassObject; [aClassTemp methodOfAClass]; aClassTemp.propertyOfAClass = someValue; }

if ([someClassObject respondsToSelector:@selector(methodOfBClass:)) [someClassObject perforformSelector:@selector(methodOfBClass:) withObject:[UIColor clearColor]];

Note the number of : following the selector name correlates to the number of parameters of the method. You may not find a suitable variance of performSelector for each possible method call. Especially as you can pass or return references to objects only.

Again, both of them I would only suggest if the common subclass is not suitable in your case.

Upvotes: 0

rakeshNS
rakeshNS

Reputation: 4257

Try this,

id graphv;

if ([type isEqualoString:@"day"]) {
    (GraphDayView *)graphv = [[GraphDayView alloc] initWithFrame:rect];
} else {
    (GraphMonthView*)graphv = [[GraphMonthView alloc] initWithFrame:rect];
}

Upvotes: 0

Hot Licks
Hot Licks

Reputation: 47729

Make GraphDayView and GraphMonthView both subclasses of GraphCalendarView. Then make your backgroundColor a property of GraphCalendarView.

(Or, if your two classes are already subclasses of a UI class that implements backgroundColor then you're home free.)

Declare your variable as GraphCalendarView graphv;, and then proceed as before. If you need to use a property/method that's unique to of one or the other of your two derived classes then cast to that class first.

Upvotes: 1

TigerCoding
TigerCoding

Reputation: 8720

If they share the same superclass, then use that instead of id. Otherwise, create two variables and set them to nil:

GraphDayView *gdv = nil;
GraphMonthView *gmv = nil;

Then test after the if statement to see which one was initialized.

Upvotes: 2

Related Questions