2009-07-08 2 views
9

Я изучаю ObjectiveC и сталкивался с проблемой, связанной с самоанализом. В принципе, я перебираю массив объектов и определяю, принимают ли они переключатель lowercaseString. Если они это сделают, я вызываю этот селектор объекта. После того, как я гарантирую, что объект отвечает на этот селектор, я вызываю его. Однако, когда я это делаю, я получаю это предупреждение: «предупреждение:« NSObject; может не отвечать на «-lowercaseString»Избавиться от «NSObject» может не отвечать на предупреждение «-Momeod»

Хотя код работает отлично, как написано, я бы не хотел получать предупреждение. Я предполагаю, что есть «правильный» способ убедиться, что я не получаю это предупреждение (т. Е. Не выключая предупреждения). Есть идеи?

NSMutableArray *myArray = [[NSMutableArray alloc] init]; 

[myArray addObject:@"Hello!"]; 
[myArray addObject:[NSURL URLWithString:@"http://apple.com"]]; 
[myArray addObject:[NSProcessInfo processInfo]]; 
[myArray addObject:[NSDictionary dictionary]]; 

SEL lowercaseSelector = @selector(lowercaseString); 

for (NSObject *element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([element lowercaseString]); // Warning here 
    } 
} 
+0

Кроме того, если у меня неправильная терминология «селектора», пожалуйста, исправьте меня. :) – Tyson

+3

* Не * передавать непостоянные строки в NSLog. Существует риск для безопасности. Вы можете подумать, что в этом случае вы в безопасности, но не привыкните к этому. Вы неизбежно закончите это в случае, когда откроете дыру в безопасности. – kperryua

+0

У вас есть ссылка на дополнительную информацию об этом бремени безопасности? Мне определенно интересно узнать больше об этом. – Tyson

ответ

15

Вы также можете использовать id, который является любой тип объекта.

for (id element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([element lowercaseString]); 
    } 
} 
+0

Я полагал, что NSObject будет правильным, но, действительно, id - лучший способ сделать это. – Tyson

+0

до тех пор, пока вам не нужно вызывать сохранение или освобождение на элементе ;-) –

+0

что не так с вызовом retai/release на id? –

4

Просто отдать свой NSObject к NSString перед вызовом функции:

for (NSObject *element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([(NSString*)element lowercaseString]); // No warning! 
    } 
} 
+0

Но что, если объект не поддерживает все селекторы, поддерживаемые NSString? Мой ООП-смысл подсказывает мне, что это будет плохо. Я просто проверяю один селектор, независимо от того, какой суперкласс принадлежит ему. – Tyson

+0

Ну, вы предполагаете, что -lowercaseString возвращает NSString, так как NSLog ожидает строку формата. Если по какой-либо причине он не возвращает NSString, то вы передаете что-то другое, кроме NSString, в качестве строки формата, и NSLog захлебнется. –

+0

Самым безопасным способом было бы получить 'lowercaseString', сохранить его в переменной и проверить, является ли это своего рода NSString. Вы, вероятно, не должны быть тем параноиком, хотя, и если вы этого не сделаете, вы можете также объявить переменную как или передать возвращаемое значение в 'NSString *'. –

6

Как об использовании performSelector:?

SEL lowercaseSelector = @selector(lowercaseString); 

for (NSObject *element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([element performSelector:lowercaseSelector]); // No warning 
    } 
} 

Это избавит вас от предупреждения о компиляторе.

+0

А это похоже на хороший способ сделать это. Спасибо за ответ. – Tyson

1

Кастинг как идентификатор снят с предупреждения.

if ([self.content respondsToSelector:@selector(setDelegate:)]) 
{ 
    [(id)self.content setDelegate:nil]; 
} 
Смежные вопросы