OC 中,覆盖属性会有怎么样的化学反应?

原创 2015年11月19日 18:01:18

首选须知:摘自:github上《招聘一个靠谱的iOS》面试题参考答案(上).md

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

  1. @property有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var;
  2. @synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。
  3. @dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

在编写一个自定义相册的功能的时候,由于需要继承 UINavigationController写一个ImagePickerViewController,同时ImagePickerViewController又需要和其他的类进行沟通,所以很自然的,ImagePickerViewController类就需要有一个delegate属性,而且需要要求这个属性是一个实现了自定义的ImagePickerViewControllerDelegate协议的属性,那么这个时候问题就来了:父类是已经有一个这样的属性的。直接这么写编译器就会给出一个 warning

Auto property synthesis will not synthesize property 'delegate'; it will be implemented by its superclass, use@dynamic to acknowledge intention

诚然我们可以通过声明一个类似delegateObj的属性来避开这个问题,不过为何编译器会给出这个 warning 却值得研究。

要想研究这个问题首先得从什么是属性开始讲起,在 oc 中属性就是给一个类的成员变量提供封装:

Objective-C properties offer a way to define the information that a class is intended to encapsulate。

通过声明属性,我们可以很简单的为一个成员变量定义其是否是只读的还是读写的,是否是原子操作的等等特性,也就是说如果说封装是为成员变量套了一层壳的话,那么 @property关键字做的事情就是预定义这层壳是个什么样子的壳,然后通过 @sythesize关键字生成真正的壳并把这个壳套在实际的成员变量上(如果没有定义这个成员变量该关键字也可以自动生成对应的成员变量)。当然这层壳包括了自动生成的 get set 方法。
在最开始的时候,我们在代码中写了@property对应的就要写一个@sythesize,在苹果使用了 LLVM 作为编译器以后,如果我们没有写 @sythesize,编译器就会为我们自动的生成一个 @sythesize property = _property。这个特性叫做Auto property synthesize

说了这么多,现在我们来回头看看问题的关键,当我们想覆盖父类的属性并做一些修改的时候,Auto property synthesize这个特性就有点不知道该干嘛了,这个时候他选择不跑出来为我们干活,所以编译器就不会自动生成@sythesize property = _property,但是子类总得有个壳啊,人家都有@property了,怎么办?直接拿过来父类的壳复制一份不管三七二十一套在子类的成员变量身上。注意,有些情况下这会产生运行时的 crash,比如:
一个父类 A

@interface A : NSObject
@property(strong,nonatomic,readonly)NSString *name;

子类 Aa

@interface Aa : A
@property(strong,nonatomic,readwrite)NSString *name;

这种情况下编译器会给出 warning:

Auto property synthesis will not synthesize property 'name' because it is 'readwrite' but it will be synthesized 'readonly' via another property

注意,虽然只给出了 warning,但是这个时候显然 Aa 中是不会自动生成 set 方法的,如果在代码中调用了 Aa 的实例对象的 set 方法,运行时就会 crash,crash 原因是:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Aa setName:]: unrecognized selector sent to instance

所以遇到这个问题怎么解决?在子类中显式的声明一个@synthesize name = _name;就好,这样子类就会如愿的产生他的壳,编译器也不纠结了,就去掉了 warning,从此,天下太平~

OC 中 覆盖属性会有提示Auto property synthesis will not synthesize property 'delegate'

在编写一个自定义相册的功能的时候,由于需要继承 UINavigationController写一个ImagePickerViewController,同时ImagePickerViewControll...

NSString为什么要用copy关键字,如果用strong会有什么问题 OC中的深拷贝与浅拷贝

首先说一下深拷贝和浅拷贝,深拷贝是内存拷贝,浅拷贝是指针拷贝 写代码的时候有两个copy方法 - (id)copy; - (id)mutableCopy; copy出的对象为不可变类型     ...

OC 中,子类覆盖父类属性 详解

http://segmentfault.com/a/1190000002904657 OC 中,覆盖属性会有怎么样的化学反应? 在编写一个自定义相册的功能的时候,由于需要继承 UINavi...
  • jeffasd
  • jeffasd
  • 2016年01月07日 13:21
  • 5587

java中实例子类会有父类对象产生吗?如果不产生父类对象为什么子类有父类的属性和方法?

首先第一个问题: 子类在创建实例后,类初始化方法会调用父类的初始化方法(除了java.lang.Object类,因为java.lang.Object类没有父类),而这种调用会逐级追述,直到java.l...

oracle的神奇化学反应

乐享云之天 2017-05-11 16:56 橘子+汽水=橘子汽水,∑(゚Д゚ノ)ノ好无聊!!! 火鸡+烤架=烤火鸡,ლ(´ڡ`ლ)还不错. wm_concat+表字段查询=(✪ω✪)会是啥...

OC 自动生成分类属性方法

分类属性方法自动生成编码全过程。 背景   分类,在 iOS 开发中,是常常需要用到的。在分类里添加属性也是常有的事,但分类中无法添加实例变量,编译器也无法为提供分类中属性的 getter...

OC 实例变量(instance var)与属性(@property)的关系

01).@property01>.自动生成getter 和 setter 方法的声明自动给当前类生成一个私有属性(在@implementation中),这个属性名称自带下划线 自动生成getter ...

OC-----属性及点语法

1.属性 属性是Objective-C 2.0定义的语法,为实例变量提供了setter、getter⽅方法的默认实现能在⼀定程度上简化程序代码,并且增强实例变量的访问...

iOS开发-OC中属性创建需要注意的地方(property实例变量的创建和标准存取方法)

现在很多人都不太会使用属性,而且把控不住内存,导致崩溃异常等情况。用的时候不去思考怎么使用更加严谨,防止发生其他的情况。 那么我就说说property 的内存管理如何去把控防止出现糟糕的情况:...

OC 创建一个Fraction类(分数)实现分数的加减乘除,比较大小、约分等方法。 要求:为类添加属性

#import /*创建一个Fraction类(分数)实现分数的加减乘除,比较大小、约分等方法。 要求:为类添加属性 */ @interface Fraction : NSObject { ...
  • MHTios
  • MHTios
  • 2014年08月12日 21:14
  • 5415
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OC 中,覆盖属性会有怎么样的化学反应?
举报原因:
原因补充:

(最多只允许输入30个字)