для циклов - Тип объекта игнорируется? - PullRequest
7 голосов
/ 18 августа 2011

Мне иногда нравится организовывать элементы IB в NSArray s в первую очередь, чтобы помочь мне организовать свои элементы.Чаще всего разные классы объектов превращают его в один массив друг с другом.Хотя это является удобным способом организации, я не могу понять, почему, если у меня есть такой массив:

NSArray *array = [NSArray arrayWithObjects:((UITextField *)textField), ((UISegmentedController *)segmentedController), nil];

Почему я получаю "Не отвечаетдля выбора сообщений, когда я помещаю цикл for следующим образом:

for (UITextField *text in array) {
    [text setText:@""];
}

Кажется, что в цикл for передаются объекты, которые не относятся к классу UITextField.

Чтосмысл объявлять класс объекта, если все объекты в указанном массиве передаются через цикл?

EDIT Просто для справки, вот как я сейчас работаю с ним:

for (id *object in array) {
    if ([object isMemberOfClass:[UITextField class]]) {
        foo();
    } else if ([object isMemberOfClass:[UISegmentedController class]) {
        bar();
    }
 }

Ответы [ 3 ]

10 голосов
/ 18 августа 2011

Когда вы делаете

for (UITextField *text in...

, указатели объектов из массива приводятся к типу UITextField * - поэтому, если объект на самом деле не является UITextField, могут произойти всевозможные странные вещи, если вы попытаетесьвызовите методы UITextField.

Поэтому вместо этого используйте тип идентификатора (no * required, btw):

for (id obj in array)

Затем проверьте тип, как вы это делаете, и вызовите соответствующие методы.Или отфильтруйте массив, чтобы получить только объекты определенного типа, а затем выберите только этот тип:

for (UITextField* text in [array filteredArrayUsingPredicate:...])

Редактировать: вот как построить предикаты фильтра класса:

Isможно отфильтровать NSArray по классу?

5 голосов
/ 18 августа 2011

Какой смысл объявлять класс объекта, если все объекты в указанном массиве передаются через цикл?

Имя класса только для того, чтобы компилятор знал, что онследует ожидать, чтобы найти.Это позволяет ему выяснить, какие методы следует ожидать от вас и как вы можете обращаться с объектом.Это та же идея, что и передача int методу, который принимает float.Метод не будет игнорировать целые числа - он предполагает, что вы передаете правильный тип.Вы просто даете этой конструкции немного больше доверия, чем нужно:

for (UITextField *text in array)

Она просто не имеет такой функциональности.Как вы справляетесь с этим сейчас - правильный путь.

0 голосов
/ 18 августа 2011

Вы уверены, что не получаете сообщение об ошибке, когда запускаете этот код?Сообщение «не отвечает селектору» - это ошибка времени выполнения, а не ошибка времени компиляции.Компилятор не знает, реализуют ли объекты в массиве -setText:, но вы обязательно должны получить сообщение об ошибке, когда отправляете это сообщение экземпляру UISegmentedControl.

Другая возможность заключается в том, что выполучил класс с именем UISegmentedController, который имеет метод -setText:.Имя класса, реализующего многочастный виджет пользовательского интерфейса в виде гистограммы, - UISegmentedControl.Так что либо код, который вы показываете, не является реальным, проверенным кодом, или у вас есть класс, о котором мы не знаем.

...