您的位置:首页 > 运维架构

OC基础—内存管理之@property及其参数(补充新知识:循环引用和@class)

2014-04-26 23:48 459 查看
------ android培训java培训、期待与您交流! ----------

     内存管理之@property

内存管理之@property:

我们可以利用@property简化我们内存管理代码。

之前我们手管理内存的时候,总要写大量相同的set,get方法,来确保内存管理的严谨性,但是这样的代码没有什么技术含量,而且量又大,不利于我们编写有用代码,这时我们可以利用@property来自动生成这些管理内存的get set方法。

现在我们有Person类和Book类的组合:看一下Person类

Person.h

#import <Foundation/Foundation.h>
#import "Book.h"

@interface Person : NSObject

// retain:给旧值release,给新值retain
// dealloc里还是要自己释放的
@property (retain) Book *book;
@property (retain) NSString *name;

@end


Person.m

#import "Person.h"

@implementation Person

//- (void)setBook:(Book *)book
//{
//    if ( book != _book) {
//
//        // 对当前正在使用的车release
//        [_book release];
//
//        // 对新车做一次retain
//        _book = [book retain];
//    }
//}
- (void)dealloc
{
[_book release];
[_name release];
[super dealloc];
}
@end

现在我们可以看到只要在@property后面加一个retain那么,.m文件中自动生成的set方法就是这个样子的

- (void)setBook:(Book *)book
{
if ( book != _book) {

// 对当前正在使用的车release
[_book release];

// 对新车做一次retain
_book = [book retain];
}
}


这样就不需要我们自己来管理set方法的内存了,也不用再写那些臃肿的代码了,只需要一句话

@property (retain) Book *book;

就可以自动生成那些重发的代码了。

当人@property是不会自动给你生成dealloc方法的,所以的dealloc方法还是要我们自己来写的,不要忘了对象的release。

@property参数

@property不光有retain这个参数,他有四大类参数

1.内存管理相关的参数

* retain: release旧值,retain新值(适用于OC对象)

* assign: 直接赋值 (默认)

* copy : release旧值,copy新值

2.是否生成set方法

* readwrite : 同时生成setter和getter的声明与实现(默认)

* readonly : 只会生成getter方法的声明与实现

3.多线程管理

* nonatomic : 性能高(一般就用这个)

* atomic : 性能低(默认)

4.setter和getter方法名称

* seteer : 决定了set方法的名称 一定要加:

* getter : 决定了getter方法的名称(一般用在BOOL类型)

来一个例子:

Person.h文件
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (getter = isRich) BOOL rich; // 给get方法取名

@property (getter = abc, setter = setAbc:, nonatomic, readwrite, assign) int weight;
// 参数是可以写在一起的
// setWight
// weight

@property  int age;
@property (readwrite) int height;
@property (retain) NSString *name;

@end

循环引用:

循环引用:我们来看个例子

两个类Person和Card

Person.h
#import <Foundation/Foundation.h>
#import "Card.h"

@interface Person : NSObject

@property (nonatomic, retain) Card *card;

@end

Card.h
#import <Foundation/Foundation.h>
#import "Person.h"

@interface Card : NSObject

@property (nonatomic, assign) Person *person;

@end


这就是循环引用,你引用我我引用你。

但是像上面这一样写会报错,Person.h里#import “Card”,Card.h里#import “Person.h”,这样会报一个重复声明的错误。那么如何解决这种问题呢,这个时候我们就用到@class这个东西。如下

#import <Foundation/Foundation.h>

// 声明一个类:告诉我们Card是一个类,不知道里面变量 方法
@class Card;

@interface Person : NSObject

@property (nonatomic, retain) Card *card;

@end

#import <Foundation/Foundation.h>

@class Person;

@interface Card : NSObject

@property (nonatomic, assign) Person *person;

@end


我们不用#import,而是声明一个类,不知道变量和方法,只知道名称用@class,像是在Person.h里面@class Card这样我们就可以

@property (nonatomic, retain) Card *card;

这样写,而不必在#import “Card”,这样可以防止重复引用,重复声明,等到我们在Person.m里用到Card的变量和方法时,在#import相应的.h文件。看一下Person.m文件

#import "Person.h"
#import "Card.h" // 在这里导入

@implementation Person

- (void)dealloc
{
NSLog(@"person被销毁了");
[_card release];
[super dealloc];
}

@end


还有一个只一点就是,循环引用的是有就是两个不能同时使用retain这个@property参数,必须一个用retain一个用assign,对象无法被销毁。

总结一下:

1.@class :仅仅声明一个类,不包含类里的成员变量和方法,故无法访问。

2.开发中引用一个类的时候,规范(为了性能着想)

1. 在.h文件中用@class来声明类

2. 在.m文件中用#import来包含类的所有东西

为什么用@class而不用#import:

1. 可以解决循环引用问题

2. 可以提高性能

两端循环引用解决方案!!!(面试题)

1. 一端用retain

2. 一端用assign

------ android培训java培训、期待与您交流! ----------


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐