@dynamic与@synthesize

@dynamic介绍:
        Apple的解释:
  @dynamic
  You use the @dynamic keyword to tell the compiler(编译器) that you will fulfill the API contract(协议合同) implied(隐藏的暗示的) by a property either by providing method implementations directly or at runtime using other mechanisms(机制机理) such as dynamic(动态的活跃的) loading of code or dynamic method resolution. It suppresses(取消抑制禁止) the warnings that the compiler would otherwise(否则) generate if it can"t find suitable implementations. You should only use it if you know that the methods will be available at runtime.
  The example shown in Listing 5-3 illustrates([ˈɪləˌstreɪt]举例说明) using @dynamic with a subclass of NSManagedObject.
  Listing 5-3 Using @dynamic with NSManagedObject
  @interface MyClass : NSManagedObject
  {
  }
  @property(nonatomic, retain) NSString *value;

  @end

  @implementation MyClass
  @dynamic value;
  @end

  NSManagedObject is provided by the Core Data framework. A managed object class has a corresponding([ˌkɔrəˈspɑndɪŋ]对应相应) schema(['ski:mə]框架模式) that defines attributes and relationships for the class; at runtime, the Core Data framework generates accessor methods for these as necessary(必须必要). You therefore typically declare properties for the attributes and relationships, but you don"t have to implement the accessor methods yourself, and shouldn"t ask the compiler to do so. If you just declared the property without providing any implementation, however, the compiler would generate a warning. Using @dynamic suppresses the warning.

  大概的翻译一下:
  @dynamic 就是要来告诉编译器,代码中用@dynamic修饰的属性,其getter和setter方法会在程序运行的时候或者用其他方式动态绑定,以便让编译器通过编译。其主要的作用就是用在NSManageObject对象的属性声明上,由于此类对象的属性一般是从Core Data的属性中生成的,Core Data框架会在程序运行的时候为此类属性生成getter和Setter方法。
        NSManagedObject属于Core Data框架。管理对象类有相应的架构定义实体的属性和关系;核心数据框架在运行时,一定会产生这些的存取方法。因此,您通常会声明的属性和关系属性,但你不需要生成自己的访问方法,也不应该要求编译器生成。然而,如果你只是声明属性但是不提供任何实现方法,编译器会生成一个警告。使用@dynamic可以抑制这种警告的产生。

@synthesize简介
      Apple的解释:
      You use the @synthesize directive(指令) to tell the compiler that it should synthesize(综合合成) the setter and/or getter methods for a property if you do not supply them within the @implementation block. The @synthesize directive also synthesizes an appropriate(适当的合适的) instance variable if it is not otherwise declared.

两者区别:
      @dynamic这个关键词,通常是用不到的。它与@synthesize的区别在于:
      使用@synthesize,编译器会确实的产生getter和setter方法,而@dynamic仅仅是告诉编译器这两个方法在运行期会有的,无需产生警告。
      假设有这么个场景:B类、C类分别继承A类,A类实现某个协议(@protocol),协议中某个属性(somePropety )我不想在A中实现,而在B类,C类中分别实现。如果A中不写任何代码,编译器就会给出警告:

“use @synthesize, @dynamic or provide a method implementation" 这时你给用@dynamic somePropety; 编译器就不会警告,同时也不会产生任何默认代码。


附1:@synthesize obj=_obj的意义详解
        我们在进行iOS开发时,经常会在类的声明部分看见类似于@synthesize window=_window;的语句.那么,这个window是什么?_window又是什么?两个东西分别怎么用,这是一个比较基本的问题,也关乎我们理解Objective-C中对类、类的属性、类的存取器、类的局部变量的统一理解。
        在32位系统中,如果类的@interface部分没有进行变量声明,但有@property声明,在类的@implementation部分有相应的@synthesize,则会得到类似下面的编译错误:
Synthesized property 'xX' must either be named the same as a compatible ivar or must explicitly name an ivar
       在64-bit时,运行时系统会自动给类添加变量,添加的变量以一个下划线"_"做前缀。
      上面声明部分的@synthesize window=_window;意思是说,window属性为_window实例变量合成访问器方法。也就是说,window属性生成存取方法是setWindow,这个setWindow方法就是_window变量的存取方法,它操作的就是_window这个变量。通过这个看似是赋值的这样一个操作,我们可以在@synthesize中定义与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问。
下面是一个常见的例子
写法一:
@interface MyClass:NSObject
{    
        MyObjecct *_myObject;  
}  
@property(nonamtic, retain) MyObjecct *myObject;  
@end  
  
@implementatin MyClass  
@synthesize myObject=_myObject;  
 
写法二:  
@interface MyClass:NSObject
{  
        
}  
@property(nonamtic, retain) MyObjecct *myObject;  
@end  
  
@implementatin MyClass  
@synthesize myObject=_myObject;  
 
         这个类中声明了一个变量_myObject,又声明了一个属性叫myObject,然后用@synthesize生成了属性myObject的存取方法,这个存取方法的名字应该是:setmyObject和getmyObject。@synthesize myObject=_myObject的含义就是属性myObject的存取方法是做用于_myObject这个变量的。这种用法在Apple的Sample Code中很常见。
        弄明白了这个语句的意思之后,我们也就清楚了myObject和_myObject的区别,那么,在使用的时候,有什么需要注意的地方,大家应该也都清楚了。是的,myObject是属性,而_myObject才是变量,我们最终操作的变量都是myObject。

那么,同样是存取操作,语句self.nameVarPtr = [[ObjectName alloc] init]; 与语句nameVarPtr = [[ObjectName alloc] init];两种赋值方式的区别何在呢?
        self.nameVarPtr=xxx 这种赋值方式等价于调用[self setnameVarPtr:xxx], 而setnameVarPtr:xxx的方法的实现又是依赖于@property的属性的,比如retain,assign等属性。
        nameVarPtr = xxx 是赋值方式,仅仅是对一个指针进行赋值。nameVarPtr仅仅是一个指针变量,记录了xxx的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retain,assign等属性没有关系。这种赋值方式就是一个简单的指针赋值。
        综上,对成员变量进行赋值,为防内存泄露需要注意的点:
       1.self调用setter方法的方式
          ObjectName*  tmp= [[ObjectName alloc] init];
          self.nameVarPtr =tmp;                 //retainCount=2
          [tmp release];                                //retainCount=1
       2.指针赋值方式,不会调用setter方法
          nameVarPtr= [[ObjectName alloc] init]; // retainCount=1
      所以,笔者建议大家在对某个变量进行赋值操作的时候,尽量要写self.myObj = xxx; 这才是最可靠的方法。

附2:@property属性举例
       读写属性
       1.readwrite:这个属性是默认的情况,会自动为你生成存取器。默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数)
       2.readonly:只生成getter不会有setter方法。将只生成getter方法而不生成setter方法(getter方法没有get前缀)
    
       赋值属性:
       3.assign:这个属性一般用来处理基础类型,比如int、float等等,如果你声明的属性是基础类型的话,assign是默认的,你可以不加这个属性.它不更改索引计数(Reference Counting).
       4.copy:这个会自动生成你赋值对象的克隆,相当于在内存中新生成了该对象的副本,这样一来,改变赋值对象就不会改变你声明的这个成员变量了。copy:指定应该使用对象的副本(深度复制),前一个值发送一条release消息。基本上像retain,但是没有增加引用计数,是分配一块新的内存来放置它。copy是建立一个索引计数为1的对象,然后释放旧对象,retain是创建一个指针,引用对象计数加1。

例如代码实现:
-(void)setThetest:(test *)newThetest {  
    if (thetest!= newThetest) {  
        [thetest release];  
        thetest= [newThetest copy];  
    }  
}  
       5.retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 ,使用retain: 对其他NSObject和其子类 ,retain,是说明该属性在赋值的时候,先release之前的值,然后再赋新值给属性,引用再加1。
例如代码实现:
-(void)setThetest:(test *)newThetest {  
    if (thetest!= newThetest) {  
        [thetestrelease];  
        thetest= [newThetest retain];  
    }  

      原子性操作
      如果使用多线程,有时会出现两个线程互相等待对方导致锁死的情况(具体可以搜下线程方面的注意事项去了解)。在没有(nonatomic)的情况下,即默认(atomic),会防止这种线程互斥出现,但是会消耗一定的资源。所以如果不是多线程的程序,打上(nonatomic)即可
       6.atomic:默认是有该属性的,就是setter/getter生成的方法是一个原子操作。这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题.
例如代码实现:
[_internal lock]; // lock using an object-level lock  
//code here...
[_internal unlock];  
       7.nonatomic:非原子性访问,不保证setter/getter的原子性,多线程情况下数据可能会有问题。如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。

参考:
http://blog.eddie.com.tw/2010/12/08/property-and-synthesize/
http://www.cocoachina.com/bbs/read.php?tid=7322
http://www.cnblogs.com/pinping/archive/2011/08/03/2126150.html

@dynamic与@synthesize相关推荐

  1. @synthesize@dynamic@private,@protected,@publicassign、weak、strong、retain、copy、nonatomic、atomic

    iOS属性修饰关键字 1. @private,@protected,@public,@package详解及使用 @privite:私有的,只有本类(不包括子类)自己拥有 @protected:受保护的 ...

  2. 属性详解(@property/@dynamic/@synthesize)

    上一篇文章讲到, OC 2.0之后属性一旦声明,如果没有readonly修饰的话,当前类自动生成了setter和getter方法的声明, 并且会自动生成对应的实例变量(下划线 + 属性名).而sett ...

  3. @property、@sythesize以及Ivar和@dynamic讲解(下)

    下面仅仅是一些基本知识,可能有些知识用的比较少,不过知道怎么使用或者了解这个知识,还是不错的,毕竟技多不压身嘛!读完这篇文章大约需要5-10分钟左右!!! 一.@property 1.在头文件中: @ ...

  4. Objective-C中的@dynamic

    Objective-C中的@dynamic 一.@dynamic与@synthesize的区别 @property有两个对应的词,一个是@synthesize,一个是@dynamic.如果@synth ...

  5. iOS面试题整理---关键字!!!

    关键字整理 static 1.static全局变量与普通的全局变量有什么区别? 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量.全局变量本身就是静态存储方式, 静态全局变量当 ...

  6. 长沙戴维营教育iOS开发面试题周刊

    [TOC] 1. 介绍一下assign, copy与retain的区别. assign 简单的指针赋值,不涉及引用计数的操作. copy 产生一个新对象,引用计数为1,老对象引用计数不变. retai ...

  7. synthesize和dynamic

    在声明property属性后,有2种实现选择 一.@synthesize 编译器期间,让编译器自动生成getter/setter方法. 当有自定义的存或取方法时,自定义会屏蔽自动生成该方法 . 二.@ ...

  8. iOS中 @synthesize 和 @dynamic 区别

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

  9. @synthesize与@dynamic

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

最新文章

  1. 互联网1分钟 |1203
  2. Android 蹲坑的疑难杂症集锦一
  3. 系统:Centos 7.2 内核3.10.0-327.el7.x86_64 # 内核需要高于2.6.32
  4. P2579,jzoj2288-[ZJOI2005]沼泽鳄鱼【矩阵乘法】
  5. Phoenix 关联查询异常 , MaxServerCacheSizeExceededException phoenix.query.maxServerCacheBytes
  6. es6 ArrayBuffer的应用
  7. 使用蒙版--渐变--制作瓶子倒影
  8. 20162303 实验五 网络编程与安全
  9. 20200213:去除重复字母(leetcode316)
  10. 三国演义词云的python代码_词云制作没那么难,Python 10 行代码就实现了!
  11. 基于windows fiber的协程(coroutine)实现
  12. vs2010旗舰版产品密钥
  13. 软考网络工程师考试大纲(2018年最新版)
  14. 论文笔记-LIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping
  15. pubg服务器维护6.23,pubg维护6月23日 | 手游网游页游攻略大全
  16. mpl代表什么_西方经济学中MPL,APL,MPK分别是什么意思
  17. 随机向量函数链神经网络(RVFLNN)
  18. 保存数据时报:Incorrect string value: '\xF0\x9F\x91\x8D' for column 'f_char_name' at row 1
  19. 电子纸驱动IC停在BUSY状态的处理办法(大连佳显)
  20. 商家收款码怎样申请做代理?共有两种途径

热门文章

  1. [机缘参悟-60]:《兵者,诡道也》-1-开篇:“死“与“生“都是天道
  2. 便携挂脖风扇开发方案
  3. 数据大放送之气候数据
  4. Linux基础知识问题解答
  5. 实现小窗口播放视频ijkplayer
  6. python 财务报表 建模_使用Python进行统计建模
  7. WJMZBMR打osu! / Easy (Lougu1365)
  8. 青龙面板京东库(4.6号更新)
  9. STM32F407ZGT6控制ESP8266与OV2640下的百度智能图片识别
  10. lda主题模型python实现篇_基于LDA主题模型的短文本分类