2012-03-17 6 views
0

Я хочу, чтобы создать объект, но тип зависит от результата условия if-:инициализации объекта, если условие

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

Проблема заключается в том, что graphv выходит за рамки, так что я не в состоянии используйте его после if-statement. Так что я попытался объявить его как идентификатор:

id graphv; 

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

Но проблема теперь в том, что компилятор не знает, какой объект grapv есть. So:

graphv.backgroundColor = [UIColor whiteColor]; 

дает ошибки. Кто-нибудь знает, как решить эту проблему?

+1

Обычно вы используете общий базовый класс в таком случае, возможно ли это здесь? –

ответ

2

Если они имеют один и тот же суперкласс, то используйте это вместо id. В противном случае создайте две переменные и установить их к нулю:

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

Затем тест после того, если заявление, чтобы увидеть, какой была инициализирована.

1

Сделайте GraphDayView и GraphMonthView обоими подклассами GraphCalendarView. Затем сделайте свой backgroundColor свойством GraphCalendarView.

(Или, если ваши два класса уже подклассы класса UI, который реализует backgroundColor то, что вы дома бесплатно.)

Объявить переменную, как GraphCalendarView graphv;, а затем продолжить, как и раньше. Если вам нужно использовать свойство/метод, который является уникальным для одного или другого из двух производных классов, тогда сначала следует применить его к этому классу.

+0

Ассумин - это подклассы UIView уже тогда, вы можете просто определить объект как экземпляр/ссылку на UIView. Это будет делать для backgroundColor. В зависимости от других методов подклассов вы можете ввести общий суперкласс betwenn UIView и ваши подклассы, как предлагает Hot Licks. –

+0

Спасибо, это сработало, хорошее решение! Один вопрос. У меня есть метод под названием «setMeasurements» в обоих подклассах. Должен ли я объявить его абстрактным методом или что лучше всего делать? – joostevilghost

+1

Либо наследуйте их от общего базового класса, который наследуется от 'UIView', например. '@interface GraphCalendarView: UIView', затем' @interface GraphMonthView: GraphCalendarView' и '@interface GraphDayView: GraphCalendarView'. ИЛИ, если они действительно не разделяют какую-либо другую общность, и вы не хотите навязывать эти отношения, вы можете создать протокол, которому они оба соответствуют, и они могут продолжать наследовать от 'UIView' –

0

Попробуйте это,

id graphv; 

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

Это само по себе может сделать код более гладким, хотя и более подверженным ошибкам. Тем не менее, graphv все еще является объектом типа id, и компилятор все равно будет вызывать предупреждение при доступе к свойству или вызове метода GraphDayView или даже UIView. При использовании ARC компилятор даже выдает ошибку и останавливает процесс сборки. –

0

Много предложений для общего суперкласса были сделаны, которые являются наиболее подходящими liekly.

В случае, если это не так, вы можете использовать typcasts. Тем не менее, приводы типов могут вызывать исключения, такие как неизвестный selecor или bad_exec. Если вы хотите, чтобы savely использовали typcasts, тогда вы всегда должны проверять либо isKindOfClass, либо отвечать наSolector.

Пример:

идентификатор someClassObject; // или любой другой общий суперкласс * вместо id

If ([something isTrue]) someClassObject = [[AClass alloc] init]; // принимаем ARC. Если нет, вы можете захотеть сохранить/autorelease здесь тоже. else someClassObject = [[AClass alloc] init];

... // некоторый код

если ([someClassObject isKindOfClass: [AClass класс]]) [(AClass *) someClassObject methodOfAClass];

// если ([someClassObject isKindOfClass: [AClass класс]]) {someClassObject AClass * aClassTemp = (AClass *); [aClassTemp methodOfAClass]; aClassTemp.propertyOfAClass = someValue; }

, если ([someClassObject respondsToSelector: @selector (methodOfBClass :)) [someClassObject perforformSelector: @selector (methodOfBClass :) withObject: [UIColor clearColor]];

Обратите внимание, что число: после имени селектора коррелирует с количеством параметров метода. Вы не можете найти подходящее отклонение функции Selectlect для каждого возможного вызова метода. Тем более, что вы можете передавать или возвращать ссылки только на объекты.

Опять же, оба из них я бы предложил только, если общий подкласс не подходит в вашем случае.

Смежные вопросы