Дилемма самомодифицирующейся категории NSString
-
19-09-2019 - |
Вопрос
Оба работают, но какой из них вы бы использовали и почему?
@implementation NSString (Extender)
-(NSString *) stringByTrimmingPrefix:(NSString *)strPrefix
{
while ([self hasPrefix:strPrefix])
{
self = [self substringFromIndex:strPrefix.length];
}
return self;
}
@end
или
@implementation NSString (Extender)
-(NSString *) stringByTrimmingPrefix:(NSString *)strPrefix
{
NSString *returnValue = [NSString stringWithString:self];
while ([returnValue hasPrefix:strPrefix])
{
returnValue = [returnValue substringFromIndex:strPrefix.length];
}
return returnValue;
}
@end
Решение
Вариант №2.
NSString задуман как неизменяемый объект.Все стандартные методы «stringBy» в NSString возвращают новые автоматически выпущенные NSString.
Хотя #1 также возвращает новую NSString, она в лучшем случае семантически неверна, а в худшем — изменяет объект, на который ссылается, на то, что должно было быть неизменяемым объектом.
Другие советы
Во-первых, ваше определение метода Objective-C в точности эквивалентно этой функции C:
NSString* stringByTrimmingPrefix(NSString* self, SEL _cmd, NSString* strPrefix)
{
...
}
Как вы видете, self
это просто еще один параметр функции;вы можете переназначить его чему угодно, и это не повлияет на состояние исходного экземпляра NSString*, на который он изначально указывал.
Так что в этом отношении нет ничего плохого в том, что вы делаете в своей первой реализации.
Однако ни одна из ваших реализаций не очень эффективна, и в обеих есть ошибки (что произойдет, если вы передадите префикс, содержащий более одного символа?)
я хотел бы использовать rangeOfString: параметры: диапазон: чтобы найти ваши префиксы, чтобы вы создавали не более одного дополнительного экземпляра NSString.
так что это просто отсекает одну букву в начале строки (если эта буква встречается более одного раза, она отсекает все их количество)?
Поскольку NSString является неизменяемым, я не вижу разницы в производительности.В первом случае вы каждый раз заменяете self новым строковым объектом, а во втором случае вы каждый раз заменяете returnValue новым строковым объектом.Я думаю, поскольку первый вариант сохраняет строку кода, я бы использовал его.