先说结论
- @property 这是开发中最长用到的.这是在声明一个属性名 每当我们使用 @property声明了一个变量 等于做了三件事 Ivar + set + get;
- @synthesize 可以理解为合成. 系统会自动为我们生产set + get (我认为还会为我们 声明 等号后面的 Ivar 变量)
- @dynamic 就是告诉系统@property做的三件事, 都不要做了.
结合代码说明
我使用runtime 对不同组合打印
1. 正常的写法
#import <objc/runtime.h>
@interface subViewController (){
NSString *_test2;
}
@property (nonatomic, copy) NSString *test1;
@property (nonatomic, copy) NSString *test3;
@end
@implementation subViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self getIvarName];
[self getPropertyName];
[self getMethodName];
}
// 打印 IvarList
- (void)getIvarName{
unsigned int count = 0;
Ivar *members = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = members[i];
const char *membername = ivar_getName(ivar);
NSLog(@"IvarName: %s", membername);
}
}
// 打印 PropertyList
- (void)getPropertyName{
unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([self class], &count);
for (int i = 0 ; i < count; i++) {
objc_property_t property = propertys[i];
const char *propertyName = property_getName( property);
NSLog(@"PropertyName %s", propertyName);
}
}
// 打印 MethodList
- (void)getMethodName{
unsigned int count = 0;
Method *members = class_copyMethodList([self class], &count);
for (int i = 0; i < count; i ++) {
Method mthod = members[i];
SEL mthod_s = method_getName(mthod);
const char *mthod_c = sel_getName(mthod_s);
NSLog(@"method Name :%s", mthod_c);
}
}
@end
打印信息是
IvarName: _test2
IvarName: _test1
IvarName: _test3
PropertyName test1
PropertyName test3
method Name :test1
method Name :setTest1:
method Name :test3
method Name :setTest3:
method Name :.cxx_destruct
因为_test没有用@property 所有没有set和get方法.
从这个打印我们可以看出 @property 其实干了四件事 以test1为例:
- 将tist1 放入 propertyList, 2 声明_test1 并放入IvarList, 3 声明setTest1方法 4. 声明test1 get方法.
继续测试 @dynamic;
如果在 @implementation 下一行添加
@dynamic test3;
打印信息
2017-07-17 13:36:20.952 CCNetworkHelper[1552:106531] IvarName: _test2
2017-07-17 13:36:20.953 CCNetworkHelper[1552:106531] IvarName: _test1
2017-07-17 13:36:20.953 CCNetworkHelper[1552:106531] PropertyName test1
2017-07-17 13:36:20.953 CCNetworkHelper[1552:106531] PropertyName test3
2017-07-17 13:36:20.953 CCNetworkHelper[1552:106531] method Name :test1
2017-07-17 13:36:20.953 CCNetworkHelper[1552:106531] method Name :setTest1:
对比第一打印 IvarName 中少了 _test3, methodName 中少了test3的set和get方法, 说明 @dynamic test3, 系统就只干了一件事 把test3到protertyList中.
继续测试@synthesize test1 = _test1;
如果在 @implementation 下一行添加
@synthesize test1 = _test1;
打印信息
2017-07-17 13:44:26.592 CCNetworkHelper[1577:109840] IvarName: _test2
2017-07-17 13:44:26.592 CCNetworkHelper[1577:109840] IvarName: _test1
2017-07-17 13:44:26.592 CCNetworkHelper[1577:109840] IvarName: _test3
2017-07-17 13:44:26.593 CCNetworkHelper[1577:109840] PropertyName test1
2017-07-17 13:44:26.593 CCNetworkHelper[1577:109840] PropertyName test3
2017-07-17 13:44:26.593 CCNetworkHelper[1577:109840] method Name :test1
2017-07-17 13:44:26.593 CCNetworkHelper[1577:109840] method Name :setTest1:
2017-07-17 13:44:26.594 CCNetworkHelper[1577:109840] method Name :test3
2017-07-17 13:44:26.594 CCNetworkHelper[1577:109840] method Name :setTest3:
2017-07-17 13:44:26.594 CCNetworkHelper[1577:109840] method Name :.cxx_destruct
跟第一次打印的信息一样, 说明系统默认就是这么干的.
下面是来瞎搞一下.
继续测试 如果在 @implementation 下一行
@synthesize test1 = _test2;
打印信息
2017-07-17 13:46:53.143 CCNetworkHelper[1596:111809] IvarName: _test2
2017-07-17 13:46:53.143 CCNetworkHelper[1596:111809] IvarName: _test3
2017-07-17 13:46:53.143 CCNetworkHelper[1596:111809] PropertyName test1
2017-07-17 13:46:53.144 CCNetworkHelper[1596:111809] PropertyName test3
2017-07-17 13:46:53.144 CCNetworkHelper[1596:111809] method Name :test1
2017-07-17 13:46:53.144 CCNetworkHelper[1596:111809] method Name :setTest1:
2017-07-17 13:46:53.145 CCNetworkHelper[1596:111809] method Name :test3
2017-07-17 13:46:53.145 CCNetworkHelper[1596:111809] method Name :setTest3:
2017-07-17 13:46:53.145 CCNetworkHelper[1596:111809] method Name :.cxx_destruct
对比第一次打印, _test1 没了.
于是我又做了实验 在@implementation 下添加
@synthesize test1 = _test5; // _test5以前没出现过.
打印信息
2017-07-17 13:53:48.363 CCNetworkHelper[1626:115962] IvarName: _test2
2017-07-17 13:53:48.363 CCNetworkHelper[1626:115962] IvarName: _test5
2017-07-17 13:53:48.364 CCNetworkHelper[1626:115962] IvarName: _test3
2017-07-17 13:53:48.364 CCNetworkHelper[1626:115962] PropertyName test1
2017-07-17 13:53:48.364 CCNetworkHelper[1626:115962] PropertyName test3
2017-07-17 13:53:48.364 CCNetworkHelper[1626:115962] method Name :test1
2017-07-17 13:53:48.364 CCNetworkHelper[1626:115962] method Name :setTest1:
2017-07-17 13:53:48.365 CCNetworkHelper[1626:115962] method Name :test3
2017-07-17 13:53:48.365 CCNetworkHelper[1626:115962] method Name :setTest3:
2017-07-17 13:53:48.365 CCNetworkHelper[1626:115962] method Name :.cxx_destruct
IvarName 出现了_test5;
经过这两次测试 我认为的可能:
当使用 @property (nonatomic, copy) NSString *test1;时,系统会为我们做两件事 1. 将test1 放入Property中, 2 实现语句 @synthesize test1 = _test1.
而@synthesize 会帮我们做三件事:
1. 声明Ivar _test1并放入 IvarList中
2. 生产set 方法
3. 生成get方法.
我以前一直认为这三件事是 @property做的, 从上面的实验看来这三件事也许是 @synthesize做的.
以上观点都是我测试得出的, 如果有不对的请指正
qq: 2711056454