我有一个代表一些数据的类。
我从 JSON 格式的 Web 服务获取这些数据。
Web 服务不符合 Objective-C 命名约定。更具体地说,对象的所有属性都以大写字母开头,例如 Name
.
我希望能够利用内置的 KVC,但仍然使用 Objective-C 命名约定构建我的对象。
因此,在我的公共(public)类声明中,我声明了一个属性:
@interface TVPage : NSObject
@property (nonatomic, copy) NSString *name;
@end
在我的 *.m 文件中,我声明了一个类别扩展以符合 Web 服务命名约定:
@interface TVPage ()
@property (nonatomic, copy , getter = name , setter = setName:) NSString *Name;
@end
在私有(private)属性中,我指定了我想要实际访问数据的 getter 和 setter。
我想要实现的只是另一种方法,称为
Name
实际上会调用 name
在幕后。 ( setName:
实际上适合 Name
和 name
)我的问题是,当我合成这样的属性时:
@implementation TVPage
@synthesize name;
@synthesize Name;
@end
它会生成两个不同的实例变量,称为
Name
和 name
或者它是否足够聪明,可以理解不这样做并只创建一个名为 name
的?我可以明确告诉编译器 - “不要为此属性生成 Ivar”吗?
谢谢!
编辑:
我为什么要这样做?
很多人问我到底想在这里实现什么。
好吧,在解析从 Web 服务返回的数据时,我想做的是让我的生活更轻松。
数据作为 JSON 字符串返回。这意味着当我解析它时,我可能会取回 NSDictionaries 来表示数据。
我想轻松地创建我设计用来保存这些数据的对象,因为将字典用作数据模型不方便、不安全或不可读。
现在,键值编码功能允许我直接从字典中使用
setValuesForKeysWithDictionary:
设置对象的属性。但这只有在我的对象实际上具有与字典键同名的访问器方法时才有效。如果我的对象中有一个没有匹配属性的键,我会从
setValue:forUndefinedKey:
得到一个异常。 .为了避免我想创建 Facade Interface这将符合来自服务器的属性名称所隐含的键值编码方法。同时,我希望该接口(interface)的实现将访问“常规”接口(interface)访问的相同数据。
最佳答案
正如我所说,编写一些测试代码,然后不要继续你正在做的任何事情。
@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
你看?自定义 setter/getter
name
不要求 valueForKey:@"Name"
.但是调用了自定义 setter 。但可能只是因为您不能将大写字母大写。希望大家不要盲目使用
setValuesForKeysWithDictionary:
有一堆值。无论如何,您都必须验证这些键,因为您不想为像 self
这样的键调用该方法。 , description
等等。因此,当您验证 key 时,只需“取消大写” key 的名称即可。恕我直言,删除大写字母是一种更清洁的方法,因为它不会像那些奇怪的影子变量那样发生一半的访问器方法失败。
关于objective-c - Objective C - 使用相同实例变量的两个合成属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9964578/