iOS @property、@synthesize和@dynamic
@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的更多相关文章
- iOS中 @synthesize 和 @dynamic 区别
OC object-c 为了让java的开发者习惯 使用.的操作,所以可以将接口类中的变量 使用@property来声明属性.但是在.h中声明的属性,必须在.m中使用@synthesize或者@dyn ...
- iOS中 @synthesize 和 @dynamic
今天写点过时的东西,我记得 这个是xcode 4 那个年代的事情了,没想到有时候大家还会被问到.可能目的就是看看你是从是么时候才开始接触iOS的. 在声明property属性后,有2种实现选择 @s ...
- 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方 ...
- @property、@synthesize和dynamic的用法
原文: http://blog.csdn.net/hherima/article/details/8622948 @代表“Objective-C”的标志,证明您正在使用Objective-C语言 O ...
- 李洪强iOS开发之OC语言@property @synthesize和id
OC语言@property @synthesize和id 一.@property @synthesize关键字 注意:这两个关键字是编译器特性,让xcode可以自动生成getter和setter的声明 ...
- @synthesize和@dynamic分别有什么作用?
@property有两个对应的词,一个是 @synthesize,一个是 @dynamic.如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _ ...
- OC语言@property @synthesize和id
OC语言@property @synthesize和id 一.@property @synthesize关键字 注意:这两个关键字是编译器特性,让xcode可以自动生成getter和setter的声明 ...
- 「OC」@property @synthesize和id
一.@property @synthesize关键字 这两个关键字是编译器特性,让Xcode可以自动生成getter和setter. (一)@property 关键字 @property 关键字可以自 ...
- OC的特有语法-分类Category、 类的本质、description方法、SEL、NSLog输出增强、点语法、变量作用域、@property @synthesize关键字、Id、OC语言构造方法
一. 分类-Category 1. 基本用途:Category 分类是OC特有的语言,依赖于类. ➢ 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 ● 继承 ● 分类(Categor ...
随机推荐
- 64位linux源码安装mysql
一:下载mysql http://dev.mysql.com/downloads/mysql/中的Generally Available(GA) Releases标签页,在MySQL Communit ...
- MUI - 实现关闭除指定页面外的其他所有页面的功能
实现关闭除指定页面外的其他所有页面的功能 比如在实现注销登录功能时,要保证旧有的webweiw或缓存不影响新用户的操作,就需要在跳转到登陆页面前关闭其他页面. http://www.cnblogs.c ...
- dva框架简单描述使用
首先传统的create-router-app脚手架生成的脚手架我们写仓库的时候用reducers进行调用还有thunk进行异步操作的时候,需要多层函数进行调用,这样会让我们代码进行维护的时候变得麻烦, ...
- UVa 10502【dp】
uva 10502 题意:给定01矩阵,求有多少个由1构成的矩阵.1本事也算一个矩阵. 到最后还是想不出来..... 每次枚举两行,从第i行到第j行,k枚举矩阵的宽(column).这样就相当于每次看 ...
- Java实现接口用来弥补Java单继承的缺陷
package com.test3;/** * @author qingfeng * 功能:继承类 VS 实现接口 :两者之间的关系(实现接口用来弥补Java单继承的缺陷) */public clas ...
- js+canvas制作前端验证码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- iptables 操作规则
iptables -nL查看本机关于iptables的设置情况,默认查看的是-t filter,可以指定-t nat iptables-save > iptables.rule会保存当前的防火墙 ...
- Android教程-01 Android Studio创建第一个项目
视频教程建议采用超清模式, 关注更多视频订阅我的优酷 最近一直使用Android Studio 简单把Android Studio介绍下 1. 首先介绍下 Android Studio的快捷键 由于之 ...
- Python的内置方法,abs,all,any,basestring,bin,bool,bytearray,callable,chr,cmp,complex,divmod
Python的内置方法 abs(X):返回一个数的绝对值,X可以是一个整数,长整型,或者浮点数,如果X是一个复数,此方法返回此复数的绝对值(此复数与它的共轭复数的乘积的平方根) >>> ...
- 关于XIFF开发IM的一些想法
因为发现网上XIFF的资料真的不多,何况现在gg又被和谐,查询资料很是不便.我写这篇文章的目的除了跟大家分享一些开发心得,也希望有类似经验的朋友看到文章后有机会多多交流. 之前我没有怎么接触过flas ...