@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. ios7.1安装提示"无法安装应用程序 由于证书无效"的解决方式二(dropbox被封项目转移到Appharbor上)

    6月18日起dropbox被天朝封了(这个真是无力吐槽),而ios7.1要求使用ssl安全连接,则须要又一次找到一个支持https的免费server. Appharbor是个不错的选择,操作简单.此外 ...

  2. myeclipse2013在线安装svn

    之前安装svn一直不行.弄了好久.还是在线安装方便. 在Help里面点击Install from Site,然后直接图解: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkb ...

  3. Python基础:17类和实例之一(类属性和实例属性)

    1:类通常在一个模块的顶层进行定义.对于Python来说,声明与定义类是同时进行的. 2:类属性仅与其类相绑定,类数据属性仅当需要有更加“静态”数据类型时才变得有用,这种属性是静态变量.它们表示这些数 ...

  4. @codeforces - 1214H@ Tiles Placement

    目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ 给定一个 n 点的树 ...

  5. 逆序对(POJ2299 Ultra-QuickSort)

    #include<bits/stdc++.h> using namespace std; int n; ],b[],ans;//a为待排序数组,b为临时数组,ans为逆序对数 void m ...

  6. CF986F Oppa Funcan Style Remastered

    CF986F Oppa Funcan Style Remastered 不错的图论转化题! 题目首先转化成:能否用若干个k的非1因数的和=n 其次,因数太多,由于只是可行性,不妨直接都用质因子来填充! ...

  7. saltStack_安装和使用

    服务端: yum install -y salt-master 客服端: yum install -y salt-minion 服务端启动: systemctl restartsalt-master ...

  8. oracle用索引提高效率

    索引是表的一个概念部分,用来提高检索数据的效率. 实际上,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最 ...

  9. Laravel 上传excel,读取并写入数据库 (实现自动建表、存记录值

    <?php namespace App\Http\Controllers; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminat ...

  10. Select multiple多选上移、下移

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD ...