@synthesize和@dynamic

2023-12-10 11:18
文章标签 dynamic synthesize

本文主要是介绍@synthesize和@dynamic,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. @property 


1. iOS6以后出来的关键词。


2. @property name:指示编译器自动合成setter和getter方法,编译器会自动给你生成setter(setter方法名即setName)和getter(而getter方法名即name)方法的声明以及实现还有一个以_name 的成员变量(name是你属性定义的变量名字),因此省去实例变量和属性重复输入的麻烦。


3.@property后面的关键字,这些属性修饰符大致分为四类:


(1)可变性 (Mutability)

- readonly,只生成getter方法,没有setter方法

- readwrite,是默认的


(2)内存管理 (Memory management)

- assign,是默认的,适用于内置类型(int, bool等)或者代理对象(delegate),不存在引用计数机制。

- retain,只适用于对象,不适用内置类型(int, bool等)。当使用setter方法时,将对象的引用计数加1。

- copy,使用setter方法时,拷贝一个对象,即在内存中产生新对象,而不是把原来的对象的引用计数加1。显然,复制出来的新对象的引用计数为1。


(3)并发性 (Concurrency)

- nonatomic,访问属性非原子性,一般单线程声明nonatomic,考虑到速度问题。多线程程序就不要使用nonatomic。

- atomic,访问属性原子性,与nonatomic相反。


(4)API控制 (API control)

- getter=newGetterName,指定新的getter方法名,一般重新改写BOOL实例变量的getter名。例如

@property (getter=isFinished) BOOL finished;  

setter=,指定新的setter方法名。


2. @synthesize 

1. @synthesize name:将实例变量_name名称换成name


这样写是为了区分成员变量_name和属性名称name,在.m里面使用的时候见到_name就知道是成员(实例)变量了,见到self.name就知道是属性了。另外,系统库中的所有类的声明部分都是这样写的, 总之一句话:区分成员变量名称和属性名称。使用@synthesize可以改变_name名称

2. @synthesize name = custom_name:将实例变量_name名称换成custom_name


注意:@synthesize不会影响@property产生的setter和getter方法的名称,@property和@synthesize不必成对出现。


3. setter和getter方法什么时候被调用?


例如,属性声明如下


@interface Person : NSObject
@property NSString *name; // atomic, assign, readwrite (default)
@end

有2种方法:

(1)显示调用(发送消息)

[instancePerson name]; // Call getter method
[instancePerson setName: @"niu"]; // Call setter method

(2)隐式调用(点语法)

NSString *name = instancePerson.firstName; // Call getter method
instancePerson.name = @"niu"; // Call setter method


如果在实例方法中直接使用实例变量,则不会调用对应的setter和getter方法,例如

NSString *myString = _name; // Won't call getter method


name = @"A string";// Won't call setter method

仅仅是对一个指针进行赋值。name仅仅是一个指针变量,记录了 @"A string"的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retainassign等属性没有关系。这种赋值方式就是一个简单的指针赋值。

显然直接使用实例变量会有风险,如内存泄露、循环引用等。最好访问实例变量,都通过@property产生的setter和getter方法。


4. @dynamic

如果不想编译器自作主张生成这些setter和getter方法,则使用@dynamic。


@dynamic (Xcode6以后省略这个了, 默认在 @implementation .m中添加这个@dynamic xxx; )告诉编译器,不自动生成getter/setter方法,避免编译期间产生警告,然后由自己实现存取方法或存取方法在运行时动态创建绑定:主要使用在CoreData的实现NSManagedObject子类时使用,由Core Data框架在程序运行的时动态生成子类属性。


有两种办法实现setter和getter方法:


1)自己提供setter和getter方法;


2)方法动态决议(DynamicMethod Resolution)。


举个简单例子,如下


#import <Foundation/Foundation.h>  @interface Person : NSObject  
@property (copy) NSString *name;  
@end  @implementation Person  
// @dynamic tells compiler don't generate setter and getter automatically  
@dynamic name;  
@end  int main(int argc, const charchar * argv[])  
{  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  Person *a = [[Person alloc] init];  a.name = @"Hello"; // will crash here  NSLog(@"%@", a.name);  [a release];  [pool drain];  return 0;  
} /


运行该程序,Xcode会报错“-[PersonsetName:]: unrecognized selector sent to instance 0x1001149d0”。如果将@dynamic注释掉,则一切Ok。


这里由于使用@dynamic,我们需要自己提供setter和getter方法。一般有两种方法:1)自己提供setter和getter方法,将编译器自动生成的setter和getter方法手动再写一遍;2)动态方法决议(DynamicMethod Resolution),在运行时提供setter和getter对应实现的C函数。


 对于第一种方法,需要在类中显式提供实例变量,因为@dynamic不能像@synthesize那样向实现文件(.m)提供实例变量。


#import <Foundation/Foundation.h>  @interface Person : NSObject  
{  // must provide a ivar for our setter and getter  NSString *_name;  
}  
@property (copy) NSString *name;  
@end  @implementation Person  
// @dynamic tells compiler don't generate setter and getter automatically  
@dynamic name;  // We provide setter and getter here  
- (void) setName:(NSString *)name  
{  if (_name != name) {  [_name release];  _name = [name copy];  }  
}  - (NSString *) name  
{  return _name;  
}  
@end // Person  int main(int argc, const charchar * argv[])  
{  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  Person *a = [[Person alloc] init];  a.name = @"Hello"; // Ok, use our setter  a.name = @"Hello, world";  NSLog(@"%@", a.name); // Ok, use our getter  [a release];  [pool drain];  return 0;  
} // mai


对于第二种方法,在运行时决定setter和getter对应实现的C函数,使用了NSObject提供的resolveInstanceMethod:方法。在C函数中不能直接使用实例变量,需要将ObjC对象self转成C中的结构体,因此在Person类同样需要显式声明实例变量而且访问级别是@public,为了隐藏该实例变量,将声明放在扩展(extension)中。


#import <Foundation/Foundation.h>  
#import <objc/objc-runtime.h> // for class_addMethod()  // ------------------------------------------------------  
// A .h file  
@interface Person : NSObject  
@property (copy) NSString *name;  
- (void) hello;  
@end  // ------------------------------------------------------  
// A .m file  
// Use extension to override the access level of _name ivar  
@interface Person ()  
{  
@public  NSString *_name;  
}  
@end  @implementation Person  
// @dynamic implies compiler to look for setName: and name method in runtime  
@dynamic name;  // Only resolve unrecognized methods, and only load methods dynamically once  
+ (BOOL) resolveInstanceMethod:(SEL)sel  
{  // Capture setName: and name method  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)  
{  // Implement @property (copy)  if (((Person *)self)->_name != name) {  [((Person *)self)->_name release];  ((Person *)self)->_name = [name copy];  }  
}  NSString* getName(id self, SEL _cmd)  
{  return ((Person *)self)->_name;  
}  - (void) hello  
{  NSLog(@"Hello, world");  
}  @end // Person  int main(int argc, const charchar * argv[])  
{  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  Person *a = [[Person alloc] init];  [a hello]; // never call resolveInstanceMethod  a.name = @"hello1";  NSLog(@"%@", a.name);  a.name = @"hello2";  NSLog(@"%@", a.name);  [a release];  [pool drain];  return 0;  
} // main  



这篇关于@synthesize和@dynamic的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/476955

相关文章

论文精读-Supervised Raw Video Denoising with a Benchmark Dataset on Dynamic Scenes

论文精读-Supervised Raw Video Denoising with a Benchmark Dataset on Dynamic Scenes 优势 1、构建了一个用于监督原始视频去噪的基准数据集。为了多次捕捉瞬间,我们手动为对象s创建运动。在高ISO模式下捕获每一时刻的噪声帧,并通过对多个噪声帧进行平均得到相应的干净帧。 2、有效的原始视频去噪网络(RViDeNet),通过探

【硬刚ES】ES基础(十三)Dynamic Template和Index Template

本文是对《【硬刚大数据之学习路线篇】从零到大数据专家的学习指南(全面升级版)》的ES部分补充。

Spark动态资源分配-Dynamic Resource Allocation

关键字:spark、资源分配、dynamic resource allocation Spark中,所谓资源单位一般指的是executors,和Yarn中的Containers一样,在Spark On Yarn模式下,通常使用–num-executors来指定Application使用的executors数量,而–executor-memory和–executor-cores分别用来指定每个ex

强化学习实践(二):Dynamic Programming(Value \ Policy Iteration)

强化学习实践(二):Dynamic Programming(Value \ Policy Iteration) 伪代码Value IterationPolicy IterationTruncated Policy Iteration 代码项目地址 伪代码 具体的理解可以看理论学习篇,以及代码中的注释,以及赵老师原著 Value Iteration Policy Itera

【Kubernetes】持久卷的动态供给 Dynamic Provisioning

《持久化存储》系列,共包含以下文章: K8s 持久化存储方式持久卷 PV持久卷声明 PVC持久卷的动态供给 Dynamic Provisioning 😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!! 持久卷的动态供给 Dynamic Pr

Design Pattern—— Dynamic Proxy Pattern(三) 动态代理模式

done by myself 通过下面例子,进一步演示 动态代理 的强大特性,将会体会到 相对于静态static代理,动态可实现 一个proxy代理不同的真实对象。灵活多变。只需要在Client类 调整要代理的角色,无需改动其他部分。使代理角色、真实角色的对应关系更松散了。 抽象角色: package com.proxy.severalCase;public interfa

步态识别论文Dynamic Aggregated Network for Gait Recognition(1)

摘要:步态识别在视频监控、犯罪现场侦查、社会安全等领域有着广泛的应用前景。然而,在实际场景中,步态识别往往受到多种外部因素的影响,如携带条件、穿着外套、视角多样等。近年来,各种基于深度学习的步态识别方法取得了可喜的成果,但它们倾向于使用固定权重的卷积网络提取显著特征之一,没有很好地考虑关键区域中步态特征之间的关系,忽略了完整运动模式的聚合。 在本文中,我们提出了一个新的观点,即实际的步态特征包括

C.Interface.And.Implementations—dynamic arrays的实现

1、An  array  is a homogeneous sequence of values in which the elements in the sequence are associated one-to-one with indices in a contiguous range.  2、Arrays in some form appear as built-in data typ

[Dynamic AX] Static and Dynamic Master Plans

AX当中有两种主计划: Static plan——静态主计划采用当前的数据生成净需求计划。在下一次重跑之前该计划的数据不会被更新。该计划可以作为决策的依据,被采购员或者采购计划者用于执行日常任务以及活动。 Dynamic plan——动态主计划始于相同的净需求。然而每当主数据变化的时候它可以被更新。例如创建一个新的销售订单之后,可以使得你在不影响静态主计划(他人在用)的情况下,监视订单变更

实际使用动态线程池框架dynamic-tp

实际使用动态线程池框架dynamic-tp 2024年7月21日 文章目录 实际使用动态线程池框架dynamic-tp1 背景2 明确任务范围2.1 技术选型2.2 引入dynamic-tp 2.引入时产生的问题2.1 一些遗憾 3.参数怎么跟随业务修改?参考文章: 1 背景 前段时间新入职了一家公司,组长看我已经有点开发年头了,委任给我一个大活,想让我可以监控任务队列,以