Использование константы NSString в качестве ключа для NSUserDefaults
Я использую NSUSerDefaults для хранения пользовательских настроек. Я помню, где-то читал, что настройка ключей как констант - хорошая идея, и я согласен. Следующий код - это то, что у меня есть:
[[NSUserDefaults standardUserDefaults]
setObject:[NSNumber numberWithInt:polygon.numberOfSides]
forKey:@"polygonNumberOfSides"];
Я попытался изменить это на:
@implementation Controller
NSString const *kPolygonNumberOfSides = @"polygonNumberOfSides";
-(void)savePolygonInfo {
[[NSUserDefaults standardUserDefaults]
setObject:[NSNumber numberWithInt:polygon.numberOfSides]
forKey:kPolygonNumberOfSides];
}
Пока это работает, он производит "warning: passing argument 1 of 'objectForKey:' discards qualifiers from pointer target type
". Я очень хочу, чтобы мой код не был свободен от предупреждений компилятора. Как я могу исправить это предупреждение?
Ответы
Ответ 1
Вы должны использовать:
NSString * const kPolygonNumberOfSides = @"..."; // const pointer
вместо:
NSString const * kPolygonNumberOfSides = @"..."; // pointer to const
Первый - постоянный указатель на объект NSString, а второй - указатель на постоянный объект NSString.
Это тонкая разница. Предупреждение компилятора происходит потому, что setObject:forKey:
объявляется следующим образом:
- (void)setObject:(id)value forKey:(NSString *)defaultName;
Ожидается, что аргумент defaultName
будет иметь тип NSString *
. Когда вы вместо этого передаете указатель на константу, вы дали ей что-то другое.
Обновление: Я хочу указать, что эти константы должны быть определены как static
, если они будут использоваться только из одного файла. Я говорю это, потому что сам столкнулся с этой проблемой: если вы не объявите их статическими, то они будут существовать в глобальном пространстве имен, и вы не сможете использовать переменную с тем же самым именем в другом файле. см. Константы в Objective-C для получения дополнительной информации. Чтобы объяснить на примере, это то, что я сейчас использую для ключей, которые мне нужно использовать только в одном файле .m
:
static NSString * const kSomeLabel = @"...";
Ответ 2
Не используйте const
с объектами Objective-C, они не были предназначены для его использования. NSString
объекты (среди многих других) уже неизменяемы по умолчанию в силу их дизайна, поэтому их const
бесполезно.
Как e.James предложил, вы можете использовать NSString * const
, который является постоянным указателем на NSString
. Это немного отличается от const NSString *
(эквивалентно NSString const *
), который является указателем на константу NSString
. Использование NSString * const
не позволяет переназначить kPoly
, чтобы указать на новый объект NSString
.
Ответ 3
Для доступа из других классов:
.h
extern NSString * const PolygonNumberOfSidesPrefsKey;
.m
NSString * const PolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSidesPrefsKey"
Доступ только внутри текущего класса:
.m
static NSString * const kPolygonNumberOfSidesPrefsKey = @"PolygonNumberOfSidesPrefsKey"
Ответ 4
Я бы предложил даже сделать константу более описательной. Постоянная для количества сторон многоугольника могла бы произойти откуда угодно. Как предложение, как насчет:
kDefaultsPolygonNumberOfSides;
вместо.
Ответ 5
Для получения дополнительной информации об этой проблеме есть замечательная статья о Википедии, объясняющая постоянный синтаксис с указателями: http://en.wikipedia.org/wiki/Const_correctness#Pointers_and_references