内存管理(二)
1.属性的内存管理
assign属性的内部实现
@property (nonatomic, assign) NSInteger age;
这行代码系统会自动帮我们在.h文件中声明好setter和getter方法,以及创建_age的实例变量并且在.m文件中实现


以上代码不需要我们自己写,但是如果在mrc中,setter和getter我们需要重写,因为会有内存问题具体如下:
(retain类型的对象内存管理)
setter问题一(野指针)
int main(int argc, const char * argv[]) { @autoreleasepool { NSString *name = [[NSMutableString alloc] initWithFormat:@"lisi"]; Person *p = [[Person alloc] init]; p.name = name; [name release]; NSLog(@"%@", p.name); [p release]; } return 0; }
上述代码开启僵尸模式会报
message sent to deallocated instance 0x100603540
具体情况如下分析:
(这里NSString *name = [[NSMutableString alloc] initWithFormat:@"lisi"];我之所以用NSMutableString原因是因为NSString 不会出错,我猜测NSString不是在堆开辟空间的)

解决方法 :
在setter时并没有对引用计数器进行retain操作故
- setName:(NSString *)name
{
[name retain];
_name = name;
// 写成一句 _name = [name retain];
}
setter问题二(内存泄露)
Person *person = [[Person alloc] init]; NSString *name = [[NSString alloc] initWithFormat:@"张三"]; [person setName:name]; [name release]; name = nil; NSLog(@"name = %@", [person name]); NSString *newName = [[NSString alloc] initWithFormat:@"李四"]; [person setName:newName]; [newName release]; newName = nil; NSLog(@"%@", person.name); [person release]; person = nil;
具体分析:

解决办法:
- (void)setName:(NSString *)name
{
[_name release];
_name = [name retain];
}
以上这样写会出问题,比如
p.name = name; p.name = name;
操作了两次,这样计数器就会出问题,具体问题自己想想
解决方法是
- (void)setName:(NSString *)name
{
if (name != _name)
{
[_name release];
_name = [name retain];
}
}
getter方法内存管理最好是采用
- (NSString *)name
{
return [[_name retain] autorelease];
}
这样写是苹果推荐写法,防止内存泄露
(copy 类型对象的管理)
相比较retain只需要将setter的 _name = [name retain];改为 _name = [name copy];
其他的就是一样的
因为assign类型的数据我们不用管的,其内存不是在堆上的,不是由我们管理的
但是在检测内存泄露(commd + shift + B 这快捷键是检测程序有没有内存泄露)时如果不写在写一遍会有内存泄露,这点有点问题
这里说的重写是指
@implementation Studnet
@synthesize age = _age
- (void)setAge:(NSInteger)age {
_age = age;
}
- (NSInteger)age {
return _age;
}
不写这个会有泄露,具体原因还在探索中. (转载请注明出处).

浙公网安备 33010602011771号