2015-04-07 3 views
2

Я использую objc_setAssociatedObject() таким образом:Правильный формат ключа для objc_setAssociatedObject()

objc_setAssociatedObject(myObject, @"myKey1", obj2, OBJC_ASSOCIATION_ASSIGN); 

В частности, мой ключ представляет собой строку символов, поэтому компилятор использует указатель на эту строку. Уточняю ту же строку символов в objc_getAssociatedObject():

objc_getAssociatedObject(myObject, @"myKey1"). 

Я использую эту схему в течение длительного времени без каких-либо проблем. Тем не менее, примеры на SO используют указатель на статическую переменную, поэтому теперь я понимаю, что мой метод может быть неправильным. Компилятор использует один и тот же указатель каждый раз, поэтому он всегда работает.

Является ли мой метод в порядке? Кажется, это эквивалентно использованию указателя на статическую строку. В каких обстоятельствах компилятор может хранить две разные копии моего ключа?

+0

это может помочь http://stackoverflow.com/questions/1937685/static-nsstring-usage-vs-inline-nsstring-constants – Flexicoder

ответ

1

Фактически две одинаковые строковые константы имеют один и тот же адрес, если они используются в одной и той же единицы перевода. (TU - это термин из C, в основном это означает: «Тот же файл .m».) Но это поведение не гарантируется и может измениться в будущем.

Это предостережение применимо и к строковым литералам компиляции. Исторически строковые литералы (используя синтаксис @ "...) были уникальны во всех единицах перевода во время связывания. Это деталь реализации компилятора, на которую не следует полагаться. Если вы используете такой код, используйте вместо него глобальные строковые константы (NSString * const MyConst = @ "...") или используйте isEqual :.

http://clang.llvm.org/docs/ObjectiveCLiterals.html

BTW: Вы должны использовать коллизий бесплатные ключи. MyKey не выполняет этого. Лучше использовать com.MyComponay.MyTarget.MyKey или эквивалентную нотацию rDNS.

+0

Традиционно постоянные строки C и ObjC Строковые литералы уникальны не только компилятором, но и * компоновщиком *. Поэтому сравнение их с использованием '==' в одном приложении обычно работает. Место, где это ломается, - это сравнение литералов из разных фреймворков. –

+0

@NikolaiRuhe Рамки не связаны? –

0

«Это часто рекомендуется, чтобы они ключ быть статический символ или, еще лучше, указатель на один. В принципе, любое значение, которое гарантированно будет постоянным, уникальным и контекстные для использования в добытчиками и сеттеров

Однако гораздо более простое решение существует: просто использовать селектор

objc_getAssociatedObject(self, @selector(associatedObject)) "

Обратитесь к этому для полного объяснения на связанные объекты:. http://nshipster.com/associated-objects/

1

void objc_setAssociatedObject (id object, const void *key, id value, objc_AssociationPolicy policy);

Существует три способа установить «const void *key» как уникальное ключевое слово по всему миру. Конечно, между const void *key и associated Object существует взаимно однозначное совпадение.

  • статическая переменная: &btnKey

  • @selector(methodName)

  • _cmd

1.A static variable you set enter image description here

2. @selector(methodName). enter image description here

3. _cmd вместо @selector(methodName)

*_cmd* is the the current method of the selector in OC, the same as *self* 

is current method call the object instance. 

enter image description here

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