oc内存管理中retain属性对应的setter实际语法代码实现及原理
2014-02-13 21:43
417 查看
使用@property配合@synthesize可以让编译器自动实现getter/setter方法,使用的时候也很方便,可以直接使用“对象.属性”的方法调用。而其中的assign,copy和retain三个属性及点语法在oc内存管理中起着至关重要的作用。在此仅对retain属性的实际语法代码极其原理经行剖析。
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1对其他NSObject和其子类
对参数进行release旧值,再retain新值
对参数进行release旧值,再retain新值
指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数——译者注)。
注意: 把对象添加到数组中时,引用计数将增加对象的引用次数+1。
retain的实际语法为:
- (void)setName:(NSString *)name {
if (_name != name) {
[_name release];
_ name = [name retain];
}
}
现在就让我们用下面浅显的代码来剖析下retain的实际语法原理
在main.h中
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Class_16.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Person *person1=[[Person alloc] init];//对象由alloc申请空间,引用指数加1,此时为1
Class_16 *class_16=[[Class_16 alloc] init];//同上
class_16.person=person1;//调用Class_16.m的setPerson方法 引用指数加1,此时为2
[person1 release];//person1对象release后,person1对象的引用指数减1,变为1(注:此时的person1对象的引用指数是1,占用的内存空间还未被释放)
[class_16.person eat];//eat方法用来作测验
Person *person2=[[Person alloc] init];//对象由alloc申请空间,引用指数加1,此时为1
class_16.person=person2;//class_16.person重指向person2,此时调用Class_16.m的setPerson方法此时person2引用指数
//加1,此时为2(而经过setPerson中的
[_person release];语句,使得person1指向的对象引用指数-1,变为1.从而person1指向的对象占用的空间得以释放)
[person2 release];//person1对象release后,person1对象的引用指数减1,变为1
[class_16.person eat];//eat方法用来作测验
[class_16 release]; //自动调用Class_16.m中的dealloc方法,即person2对象release,person1对象的引用指数减1,变为0,person2占用的内存被释放
}
return 0;
}
下面的getter方法中的判断条件
(_person!=person)的作用是当 Class_16 *class_16重指向的对象相同时,避免无谓的重复操作。
- (void)setPerson:(Person *)person
{
if (_person!=person) {
[_person release];
NSLog(@"%lu",[_person retainCount]);
NSLog(@"%lu",[person retainCount]);
_person=[person retain];
NSLog(@"%lu",[_person retainCount]);
}
}
====================================================
Person类的.h文件
#import<Foundation/Foundation.h>
@interface Person :NSObject
@property (nonatomic,retain)NSString *name,*type;
- (id)initWithName:(NSString
*)name andType:(NSString *)type;
+ (id)personWithName:(NSString *)name andType:(NSString *)type;
-(void)eat;
@end
person类的.m文件
#import "Person.h"
@implementation Person
@synthesize name=_name,type=_type;
- (void)setName:(NSString *)name
{
}
- (void)dealloc
{
NSLog(@"person dealloc");
[self.namerelease];
[self.typerelease];
[super
dealloc];
}
- (id)initWithName:(NSString *)name andType:(NSString *)type
{
self=[superinit];
if (self) {
self.name=name;
self.type=type;
}
returnself;
}
+ (id)personWithName:(NSString *)name andType:(NSString *)type
{
Person *person=[[Personalloc]initWithName:nameandType:type];
[person autorelease];//在某一适当时间释放
return person;
}
-(void)eat
{
NSLog(@"吃");
}
@end
====================================================
Class_16类的.h文件
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Class_16 :NSObject
@property (nonatomic,assign)Person *person;
- (id)initWithName:(Person *)person;
+ (id)class_16WithName:(Person *)person;
@end
Class_16类的.m文件
#import "Class_16.h"
#import "Person.h"
@implementation Class_16
- (void)dealloc
{
NSLog(@"person dealloc");
[self.personrelease];
[super
dealloc];
}
- (void)setPerson:(Person *)person
{
if (_person!=person) {
[_personrelease];
NSLog(@"%lu",[_personretainCount]);
NSLog(@"%lu",[personretainCount]);
_person=[personretain];
NSLog(@"%lu",[_personretainCount]);
}
}
- (id)initWithName:(Person *)person
{
returnnil;
}
+ (id)class_16WithName:(Person *)person
{
returnnil;
}
@end
====================================================
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1对其他NSObject和其子类
对参数进行release旧值,再retain新值
对参数进行release旧值,再retain新值
指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数——译者注)。
注意: 把对象添加到数组中时,引用计数将增加对象的引用次数+1。
retain的实际语法为:
- (void)setName:(NSString *)name {
if (_name != name) {
[_name release];
_ name = [name retain];
}
}
现在就让我们用下面浅显的代码来剖析下retain的实际语法原理
在main.h中
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Class_16.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Person *person1=[[Person alloc] init];//对象由alloc申请空间,引用指数加1,此时为1
Class_16 *class_16=[[Class_16 alloc] init];//同上
class_16.person=person1;//调用Class_16.m的setPerson方法 引用指数加1,此时为2
[person1 release];//person1对象release后,person1对象的引用指数减1,变为1(注:此时的person1对象的引用指数是1,占用的内存空间还未被释放)
[class_16.person eat];//eat方法用来作测验
Person *person2=[[Person alloc] init];//对象由alloc申请空间,引用指数加1,此时为1
class_16.person=person2;//class_16.person重指向person2,此时调用Class_16.m的setPerson方法此时person2引用指数
//加1,此时为2(而经过setPerson中的
[_person release];语句,使得person1指向的对象引用指数-1,变为1.从而person1指向的对象占用的空间得以释放)
[person2 release];//person1对象release后,person1对象的引用指数减1,变为1
[class_16.person eat];//eat方法用来作测验
[class_16 release]; //自动调用Class_16.m中的dealloc方法,即person2对象release,person1对象的引用指数减1,变为0,person2占用的内存被释放
}
return 0;
}
下面的getter方法中的判断条件
(_person!=person)的作用是当 Class_16 *class_16重指向的对象相同时,避免无谓的重复操作。
- (void)setPerson:(Person *)person
{
if (_person!=person) {
[_person release];
NSLog(@"%lu",[_person retainCount]);
NSLog(@"%lu",[person retainCount]);
_person=[person retain];
NSLog(@"%lu",[_person retainCount]);
}
}
====================================================
Person类的.h文件
#import<Foundation/Foundation.h>
@interface Person :NSObject
@property (nonatomic,retain)NSString *name,*type;
- (id)initWithName:(NSString
*)name andType:(NSString *)type;
+ (id)personWithName:(NSString *)name andType:(NSString *)type;
-(void)eat;
@end
person类的.m文件
#import "Person.h"
@implementation Person
@synthesize name=_name,type=_type;
- (void)setName:(NSString *)name
{
}
- (void)dealloc
{
NSLog(@"person dealloc");
[self.namerelease];
[self.typerelease];
[super
dealloc];
}
- (id)initWithName:(NSString *)name andType:(NSString *)type
{
self=[superinit];
if (self) {
self.name=name;
self.type=type;
}
returnself;
}
+ (id)personWithName:(NSString *)name andType:(NSString *)type
{
Person *person=[[Personalloc]initWithName:nameandType:type];
[person autorelease];//在某一适当时间释放
return person;
}
-(void)eat
{
NSLog(@"吃");
}
@end
====================================================
Class_16类的.h文件
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Class_16 :NSObject
@property (nonatomic,assign)Person *person;
- (id)initWithName:(Person *)person;
+ (id)class_16WithName:(Person *)person;
@end
Class_16类的.m文件
#import "Class_16.h"
#import "Person.h"
@implementation Class_16
- (void)dealloc
{
NSLog(@"person dealloc");
[self.personrelease];
[super
dealloc];
}
- (void)setPerson:(Person *)person
{
if (_person!=person) {
[_personrelease];
NSLog(@"%lu",[_personretainCount]);
NSLog(@"%lu",[personretainCount]);
_person=[personretain];
NSLog(@"%lu",[_personretainCount]);
}
}
- (id)initWithName:(Person *)person
{
returnnil;
}
+ (id)class_16WithName:(Person *)person
{
returnnil;
}
@end
====================================================
相关文章推荐
- 有一个NSStirng类型,retain方式声明的name属性的setter方法内部每一行代码的作用?
- 假设synthesize省略,语义属性声明assign retain copy时间,为了实现自己的setter和getter方法
- UIScrollView原理、属性、代理方法及有关功能实现(用纯代码方式)
- 用冒泡的方式对数组进行排序, 并写出对应的优化后的代码实现。(重点写思路、原理)
- 用选择的方式对数组进行排序,并写出对应的优化后的代码实现。(重点写思路、原理)
- 当把属性的语义特性分别声明为assign,retain,copy时, 自动生成setter, getter方法内部实现
- @property 属性 assign retain copy的setter方法的内部实现
- 十三种基于直方图的图像全局二值化算法原理、实现、代码及效果
- MD5原理及c#代码实现
- mvvm双向绑定机制的原理和实现代码(推荐)
- 实际案例:在现有代码中通过async/await实现并行
- silverlight2实现播放器的简单原理及其mediaelement的属性介绍
- Java NIO原理 图文分析及代码实现
- 读取JPG图片的Exif属性(三) - Exif属性读取GPS信息代码(C/C++实现)
- OC属性中setter和getter的实现
- 找出layout中的xml属性在代码中的对应方法
- PHP实现阶乘的原理与代码分析
- php 修改、增加xml结点属性的实现代码
- Java NIO原理图文分析及代码实现
- jquery 获取自定义属性(attr和prop)的实现代码