@property

@property的本质:

@property = ivar(实例变量) + getter/setter(存取方法);

在正规的 Objective-C 编码风格中,存取方法有着严格的命名规范。 正因为有了这种严格的命名规范,所以 Objective-C 这门语言才能根据名称自动创建出存取方法。

完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,这个过程由编译 器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。

我们每次在增加一个属性,系统都会在 ivar_list 中添加一个成员变量的描述,在 method_list 中增加 setter 与 getter 方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后给出 setter 与 getter 方法对应的实现,在 setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转.

@property有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var;

@synthesize

@synthesize表示如果属性没有手动实现setter和getter方法,编译器会自动加上这两个方法。
@dynamic

@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。假如一个属性被声明为 @dynamic var,而且你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

例如:

#import <Foundation/Foundation.h>

@interface People : NSObject

@property (nonatomic, copy) NSString *name;

@end

#import "People.h"

@implementation People

@dynamic name;

@end

当执行到:

   People *p= [People new];
p.name = @"Peter";

程序就会crash,原因是“[People setName:]: unrecognized selector sent to instance”。

解决这种奔溃的方法有三种:

方法一:

最简单粗暴,但是还是挺管用,直接注释掉@dynamic name这行代码即可,由编译器自动添加。

但是如果我们不想让编译器自动添加,那么我们可以手动添加或则在运行时添加都可以。

方法二:

手动添加,由于@dynamic不能像@synthesize那样向实现文件(.m)提供实例变量,所以我们需要在类中显式提供实例变量。

#import <Foundation/Foundation.h>

@interface People : NSObject

@property (nonatomic, copy) NSString *name;

@end

#import "People.h"

@interface People ()
{
NSString *_name;
}
@implementation People @dynamic name; - (void)setName:(NSString *)name { _name = [name copy];
} - (NSString *)name { return _name;
} @end

方法三:

通过runtime机制在运行时添加属性的存取方法。

在C函数中不能直接使用实例变量,需要将Objc对象self转成C中的结构体,因此在Person类同样需要显式声明实例变量而且访问级别是@public

#import <Foundation/Foundation.h>

@interface People : NSObject

@property (nonatomic, copy) NSString *name;

@end

#import "People.h"
#import <objc/objc-runtime.h> @interface People ()
{
@public
NSString *_name;
}
@end @implementation People @dynamic name; + (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(setName:)) { class_addMethod([self class], sel, (IMP)setName, "v@:@");
return YES;
}else if (sel == @selector(name)){ class_addMethod([self class], sel, (IMP)getName, "@@:");
return YES;
} return [super resolveInstanceMethod:sel];
} void setName(id self, SEL _cmd, NSString* name)
{ if (((People*)self)->_name != name) {
((People *)self)->_name = [name copy];
}
} NSString* getName(id self, SEL _cmd)
{
return ((People *)self)->_name;
}
@end
 

参考:https://www.jianshu.com/p/c883687c6405

iOS @property、@synthesize和@dynamic的更多相关文章

  1. iOS中 @synthesize 和 @dynamic 区别

    OC object-c 为了让java的开发者习惯 使用.的操作,所以可以将接口类中的变量 使用@property来声明属性.但是在.h中声明的属性,必须在.m中使用@synthesize或者@dyn ...

  2. iOS中 @synthesize 和 @dynamic

    今天写点过时的东西,我记得  这个是xcode 4 那个年代的事情了,没想到有时候大家还会被问到.可能目的就是看看你是从是么时候才开始接触iOS的. 在声明property属性后,有2种实现选择 @s ...

  3. iOS 内存管理-copy、 retain、 assign 、readonly 、 readwrite、nonatomic、@property、@synthesize、@dynamic、IB_DESIGNABLE 、 IBInspectable、IBOutletCollection

    浅谈iOS内存管理机制 alloc,retain,copy,release,autorelease 1)使用@property配合@synthesize可以让编译器自动实现getter/setter方 ...

  4. @property、@synthesize和dynamic的用法

    原文:  http://blog.csdn.net/hherima/article/details/8622948 @代表“Objective-C”的标志,证明您正在使用Objective-C语言 O ...

  5. 李洪强iOS开发之OC语言@property @synthesize和id

    OC语言@property @synthesize和id 一.@property @synthesize关键字 注意:这两个关键字是编译器特性,让xcode可以自动生成getter和setter的声明 ...

  6. @synthesize和@dynamic分别有什么作用?

    @property有两个对应的词,一个是 @synthesize,一个是 @dynamic.如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _ ...

  7. OC语言@property @synthesize和id

    OC语言@property @synthesize和id 一.@property @synthesize关键字 注意:这两个关键字是编译器特性,让xcode可以自动生成getter和setter的声明 ...

  8. 「OC」@property @synthesize和id

    一.@property @synthesize关键字 这两个关键字是编译器特性,让Xcode可以自动生成getter和setter. (一)@property 关键字 @property 关键字可以自 ...

  9. OC的特有语法-分类Category、 类的本质、description方法、SEL、NSLog输出增强、点语法、变量作用域、@property @synthesize关键字、Id、OC语言构造方法

    一. 分类-Category 1. 基本用途:Category  分类是OC特有的语言,依赖于类. ➢ 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 ● 继承 ● 分类(Categor ...

随机推荐

  1. 《C程序设计语言》笔记(三)

    六:结构 1:结构体声明中,比如: struct point{ int x; int y; }; struct后面的名字是可选的,称为结构标记.结构成员.结构标记和普通变量可以采用相同的名字,它们之间 ...

  2. dva与create-react-app的结合使用

    dva与我们的create-react-app创建的两款脚手架是我们写react项目的两款优秀框架,之前一种使用create-react-app这款脚手架进行开发.然后这个框架美中不足的是redux方 ...

  3. ssh 出错 Permission denied (publickey,password).

    将客户端的~/.ssh/know_hosts 文件删掉试试 ssh debug信息 ssh -vvv xxx@192.168.1.111

  4. ntelliJ IDEA2017 + tomcat 即改即生效 实现热部署

    1.点击idea中tomcat设置 2.点击deployment查看Deploy at the server startup 中tomcat每次所运行的包是 xxxx:war 还是其他,如果是xxxx ...

  5. laravel重定向到上一个页面怎么带参数返回 withsucess 成功提示信息

    //控制器中 return back()->with('success','操作成功'); //with的参数1是一个session变量名,参数2为该session变量值,在视图直接这样获取 @ ...

  6. java 根据秘钥,对数据进行加解密

    package test; import com.alibaba.fastjson.JSONObject; import sun.misc.BASE64Decoder; import sun.misc ...

  7. jQuery Css类

    通过 jQuery,可以很容易地对 CSS 元素进行操作 jQuery 操作 CSS jQuery 拥有若干进行 CSS 操作的方法.我们将学习下面这些: addClass() - 向被选元素添加一个 ...

  8. SDUT-3332&3333_数据结构实验之栈与队列五:下一较大值

    数据结构实验之栈与队列六:下一较大值 Time Limit: 150 ms Memory Limit: 8000 KiB Problem Description 对于包含n(1<=n<=1 ...

  9. OpenStack组件系列☞glance搭建

    第一步:glance关于数据库的操作 mysql -u root -p #登入数据库 CREATE DATABASE glance; #新建库keystone GRANT ALL PRIVILEGES ...

  10. ArrayList存储基本类型时的封装类