Цель C - Два синтезированных свойства, использующих одну и ту же переменную экземпляра? - PullRequest
1 голос
/ 01 апреля 2012

У меня есть класс, который представляет некоторые данные. Я получаю эти данные из веб-службы в формате JSON. Веб-сервис не соответствует соглашению об именах Objective-C. Более конкретно, все атрибуты объекта начинаются с заглавной буквы, например Name.

Я хочу иметь возможность использовать встроенный KVC, но по-прежнему создавать свои объекты в соответствии с соглашением об именах Objective-C.

Итак, в моем объявлении публичного класса я объявляю одно свойство:

@interface TVPage : NSObject
@property (nonatomic, copy) NSString *name;
@end

И в моем * .m файле я объявляю расширение категории в соответствии с соглашением об именах веб-служб:

@interface TVPage ()
@property (nonatomic, copy , getter = name , setter = setName:) NSString *Name;
@end

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

Все, чего я хочу добиться, - это просто еще один метод, называемый Name, который на самом деле вызовет name за сценой. (setName: на самом деле подходит для Name и name)

У меня вопрос, когда я синтезирую такие свойства:

@implementation TVPage
@synthesize name;
@synthesize Name;
@end

Будет ли он генерировать две разные переменные экземпляра, называемые Name и name, или он достаточно умен, чтобы понять, как этого не делать, и создать только одну по имени name?

Можно ли явно указать компилятору - "Не генерировать IVar для этого свойства"?

Спасибо!

EDIT:

Зачем мне это делать?

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

Данные возвращаются в виде строки JSON. Это означает, что когда я его проанализирую, я, вероятно, вернусь NSDictionaries для представления данных.

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

Теперь функции Key-Value Coding позволяют мне устанавливать атрибуты объекта прямо из словаря, используя setValuesForKeysWithDictionary:

Но это будет работать, только если у моего объекта действительно есть методы доступа с теми же именами, что и у ключей словаря. Если в моем объекте есть ключ, у которого нет соответствующего атрибута, я получу исключение из setValue:forUndefinedKey:.

Чтобы избежать этого, я хочу создать Facade Interface , который будет соответствовать методам кодирования значения ключа, подразумеваемым именами атрибутов с сервера. В то же время я хочу, чтобы реализация этого интерфейса получала те же данные, что и «обычный» интерфейс.

Ответы [ 2 ]

3 голосов
/ 01 апреля 2012

Как я уже сказал, напишите какой-нибудь тестовый код, а затем не продолжайте заниматься тем, что вы делаете.

@property (strong, nonatomic) NSString *name;
@property (nonatomic, copy , getter = name , setter = setName:) NSString *Name;

и @synthesize оба.Чтобы увидеть, что происходит, мы помещаем некоторый регистрационный код в наш s / getter, например:

- (void)setName:(NSString *)aName {
    NSLog(@"setter called");
    name = aName;
}

- (NSString *)name {
    NSLog(@"getter called");
    return name;
}

и теперь немного потестируем.

NSLog(@"setValue:forKey: with Key name");
[self setValue:@"Name" forKey:@"name"];
NSLog(@"setValue:forKey: with Key Name");
[self setValue:@"Name" forKey:@"Name"];

NSLog(@"valueForKey: with Key name");
NSLog(@"ptr: %p", [self valueForKey:@"name"]);
NSLog(@"valueForKey: with Key Name");
NSLog(@"ptr: %p", [self valueForKey:@"Name"]);

NSLog(@"\n");

NSLog(@"calling setter via dot-notation for name");
self.name = @"foo";
NSLog(@"calling setter via dot-notation for Name");
self.Name = @"foo";

NSLog(@"calling getter via dot-notation for name");
NSLog(@"ptr: %p", self.name);
NSLog(@"calling getter via dot-notation for Name");
NSLog(@"ptr: %p", self.Name);

давайте его запустим.и вуаля.

[4115:f803] setValue:forKey: with Key name
[4115:f803] setter called
[4115:f803] setValue:forKey: with Key Name
[4115:f803] setter called
[4115:f803] valueForKey: with Key name
[4115:f803] getter called
[4115:f803] ptr: 0x36d8
[4115:f803] valueForKey: with Key Name          <-----
[4115:f803] ptr: 0x0                            <-----
[4115:f803] 
[4115:f803] calling setter via dot-notation for name
[4115:f803] setter called
[4115:f803] calling setter via dot-notation for Name
[4115:f803] setter called
[4115:f803] calling getter via dot-notation for name
[4115:f803] getter called
[4115:f803] ptr: 0x3758
[4115:f803] calling getter via dot-notation for Name
[4115:f803] getter called
[4115:f803] ptr: 0x3758

Видите?Пользовательский метод получения name не вызывается для valueForKey:@"Name".Однако пользовательский установщик называется.Но, вероятно, только потому, что вы не можете использовать заглавную букву.

Я надеюсь, что вы не просто слепо используете setValuesForKeysWithDictionary: с кучей значений.Вы все равно должны проверить эти ключи, потому что вы не хотите вызывать этот метод для таких ключей, как self, description и так далее.Поэтому, пока вы проверяете ключи, просто «декапитализируйте» имена ключей.
Удаление заглавной буквы ИМХО является гораздо более чистым способом, поскольку он не завершается ошибкой для половины методов доступа, как это случилось с этими странными теневыми переменными.

1 голос
/ 01 апреля 2012

Да, вы можете сказать компилятору. Вам не нужно использовать @synthesize, но @dynamic, который просто говорит компилятору доверять вам, что где-то есть реализация, и не выдает предупреждений и т. Д.

...