Семантическая проблема: синтезированный метод получения свойства следует соглашению об именовании Какао для возврата «собственных» объектов

283

В настоящее время я использую iOS 5 SDK, пытаясь разработать свое приложение. Я пытаюсь создать свойство NSString, а затем синтезировать его в файле .m (я делал это раньше без проблем). Теперь я столкнулся с этим: «Семантическая проблема: синтезированный метод получения свойства следует соглашению об именовании Какао для возврата« принадлежащих »объектов».

Это мой код: .h

@interface ViewController : UIViewController {
     NSString *newTitle;
}
@property (strong, nonatomic) NSString *newTitle;

.m

@synthesize newTitle;

Кто-нибудь знает, как я мог это исправить? Спасибо!!

Ноам
источник
У меня была очень похожая ошибка: «Свойство следует соглашениям об именах какао для возврата« принадлежащих »объектов». Ответ Бавариуса, приведенный ниже, также, похоже, решает эту проблему.
TMin

Ответы:

606

Я предполагаю, что используемая вами версия компилятора следует правилам управления памятью и для объявленных свойств - более конкретно, для объявленных методов доступа к свойствам:

Вы вступаете во владение объектом, если создаете его с помощью метода, имя которого начинается с «alloc», «new», «copy» или «mutableCopy».

Свойство с именем newTitle, когда синтезируется, дает вызванный метод -newTitle, следовательно, предупреждение / ошибка. -newTitleпредполагается, что это метод получения для newTitleсвойства, однако в соглашениях об именах говорится, что метод, имя которого начинается с, newвозвращает объект, принадлежащий вызывающей стороне, что не относится к методам получения.

Вы можете решить это:

  1. Переименование этого имущества:

    @property (strong, nonatomic) NSString *theNewTitle;
  2. Сохранение имени свойства и указание имени получателя, которое не начинается с одного из специальных префиксов имени метода:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. Сохраняя имя свойства и имя получателя, и сообщая компилятору, что, хотя имя получателя начинается с new, оно принадлежит семейству noneметодов, а не семейству newметодов:

    #ifndef __has_attribute
    #define __has_attribute(x) 0  // Compatibility with non-clang compilers
    #endif
    
    #if __has_attribute(objc_method_family)
    #define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
    #else
    #define BV_OBJC_METHOD_FAMILY_NONE
    #endif
    
    @interface ViewController : UIViewController
    @property (strong, nonatomic) NSString *newTitle;
    - (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
    @end

    Обратите внимание, что хотя это решение позволяет вам сохранять newTitleкак имя свойства, так и имя получателя, наличие вызываемого метода -newTitle, который не возвращает объект, принадлежащий вызывающей стороне, может сбивать с толку других людей, читающих ваш код.


Для справки, Apple опубликовала примечания к выпуску «Переход к ARC» , в которых говорится:

Вы не можете дать свойству имя, которое начинается с newили copy.

Они уже были уведомлены о том, что их утверждение не совсем точное: виновником является имя метода получателя, а не имя свойства.


Редактировать 17 января 2015: Я только что заметил недавнюю фиксацию в Clang, которая предлагает описанный выше вариант 3 (с использованием objc_method_family(none)), включая исправление, для общего случая, когда имя свойства соответствует одному из префиксов семейства специальных методов. Xcode, вероятно, будет включать это изменение в конце концов.

Кер
источник
6
Работал как обаятельный человек !! Спасибо!!! Для дальнейшего использования - я использовал "@property (strong, nonatomic, getter = theNewTitle) NSString * newTitle;"
Noam
8
Прекрасный ответ. У меня были переменные с префиксом «новый».
У меня тоже есть эта проблема, и она тратит впустую много времени! Вы действительно гений ~ Спасибо!
H Lai
NS_RETURNS_NOT_RETAINEDэто то, что вам нужно тоже.
DawnSong
55

Недопустимые имена объектов

  • newButton
  • copyLabel
  • allocTitle

Допустимые имена объектов

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc # auto-synthesized # xcode-4.6.1

** РЕДАКТИРОВАТЬ **

Видимо, вы не можете использовать mutableCopy либо.

Jacksonkr
источник
1
Я также заметил, что «копия» не может быть использована на данный момент.
Ришаб
30

Имя участника, начинающееся с нового, вызывает предупреждение. Измените имя на editedTitle, и предупреждение исчезнет. Мне не удалось найти документацию, подтверждающую это, но с помощью тестирования удалось определить, что переменные-члены, начинающиеся с «new», ухудшают компилятор.

Майкл
источник
8

ARC не позволяет использовать «New ....» в имени свойства. но вы можете использовать "newTitle", изменив имя получателя.

@property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;
sooop
источник
6

Не похоже, что Бавариус предлагал то, что вы хотели сделать. Все, что вы хотите сделать, это объявить переменную экземпляра, NewTitleа затем синтезировать свойство. Мы привыкли объявлять переменную экземпляра и свойство. Больше не надо.

Теперь я считаю, что правильный способ сделать это заключается в следующем:

.час

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

@synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage

Переменная экземпляра для свойства newTitleсинтезируется. Вы не хотите, чтобы ваша переменная экземпляра была такой же, как ваше свойство - слишком легко ошибаться .

См. Пример: Объявление свойств и Синтезирование аксессоров

aquraishi
источник
Это зависит от версии компилятора. Последние версии clang выдают предупреждение в этом случае, поэтому я упомянул версию компилятора в своем ответе.
Я не думаю, что вы решили проблему. Для Xcode 9 это ошибка, а не предупреждение. NS_RETURNS_NOT_RETAINEDэто то, что вам нужно.
DawnSong
4

В CoreData, если вы используете «new ...» в атрибуте (обычно компилируется), он будет случайным образом зависать с исключением «плохой доступ».

Журнала сбоев не существует, и строка, обозначенная «Все точки исключения», вам не поможет.

лас
источник
3

Написание сеттера вручную с тем же именем, что и свойство, сняло это предупреждение.

Серж Рыковский
источник
В Xcode 7.3 это не помогло. Ошибка все еще появляется в строке определения свойства.
arlomedia
1

Помимо вопроса о том, что вы должны / не можете использовать «новый» перед своими именами свойств, скажем еще одну вещь: старайтесь избегать «нового» перед именами в целом. «Новое» зависит от времени. В настоящее время это новое для вас, но через некоторое время вы, возможно, захотите снова внедрить что-то новое. Поэтому использование «нового» в именах всегда плохо. Попытайтесь думать так: в мире программирования «новое» всегда создает что-то: новый экземпляр чего-либо.

В вашем случае, когда вы хотите назначить другой заголовок, чем текущее имя вашего свойства titleReplacement.

Еще одна вещь: попробуйте сначала назвать функции и методы с помощью глагола, например, setSomething или getSomething. Но в свойствах попробуйте сначала дать имя объекту, например, heightMinimum, heightMaximum и т. Д. -> когда вы используете инспектор при кодировании, вы всегда ищете объекты. Попробуйте это. ;-)

Филипп Шаллер
источник
1

NS_RETURNS_NOT_RETAINED используется для решения проблемы именования.

@property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;

Мы можем найти его определение следующим образом:

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

Атрибут 'ns_returns_not_retained' является дополнением к 'ns_returns_retained'. Если может показаться, что функция или метод подчиняются соглашениям Какао и возвращают сохраненный объект Какао, этот атрибут может использоваться для указания того, что возвращаемая ссылка на объект не должна рассматриваться как «принадлежащая» ссылка, возвращаемая вызывающей стороне. Платформа Foundation определяет макрос NS_RETURNS_NOT_RETAINED, который функционально эквивалентен показанному ниже.

Приложите больше деталей здесь.

DawnSong
источник
-2

попробуй это:-

@property (nonatomic,retain) NSString *newTitle;
Gypsa
источник
1
Тем не менее, точно такой же вопрос. К вашему сведению, строка ошибки находится в строке @synthesize.
Noam