------ 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培训、期待与您交流! ----------