2015-12-04 objective-c-OC_内存管理
//
// main.m
// OC_内存管理
//
// Created by YIem on 15/12/3.
// Copyright (c) 2015年 www.yiem.net YIem博客. All rights reserved.
//
import <Foundation/Foundation.h>
import "Person.h"
int main(int argc, const char * argv[]) {
// 内存管理模式
// ARC 自动引用记数
// Automtic Reference Counting
// Mrc 手动引用计数
// Manual Reference Counting
// 管理机制: 引用记数 retainCount
// 控制内存引用记数的方法
// +1
// alloc retain copy
// -1
// release autorelease
/ alloc /
// 0->1 开辟空间 任何一个alloc 对象都为1
Person *p = [[Person alloc] init];
Person *p1 = [[Person alloc] init];
/** retain **/
// +1 持有
Person *p2 = [p1 retain];
// [p2 retain];// retain 只是让引用记数+1
// Person *p2 = p1; // p2 只是p1拷贝过来的地址
// 将地址拷贝和引用记数的变化相结合 就是内存管理
// retainCount
// -1
/** release ***/
// -1 引用记数 -1
[p release];
NSLog(@"%lu", [p retainCount]);
[p1 release];
[p2 release];
// NSLog(@"%lu", [p retainCount]);
NSLog(@"%lu", [p1 retainCount]);
// NSLog(@"%lu", [p2 retainCount]);
// 创建对象
Person *pp = [[Person alloc] init];
/** copy **/
// +1
// 拷贝之后 pp对象和pp1对象是独立的两段内存空间 相互不影响
Person *pp1 = [pp copy];
NSLog(@"%@ %@", pp1, pp);
NSLog(@"%lu %lu", pp.retainCount, pp1.retainCount);
// 内存管理
[pp release];
[pp1 release];
/** autorelease **/
// 延时 -1 配合autoreleasepool(自动释放)使用
@autoreleasepool {
Person *per = [[Person alloc] init];// 0 -> 1
[per retain];// 1 -> 2
// per = nil;// 空对象
[per release];// 立马减 1 当对象为空时,什么也打印不了
// 不会立即 -1 在出自动释放池时(延迟) 对每个autorelease -1
[per autorelease];
NSLog(@"%lu", per.retainCount);
}
/*** 内存管理原则*
* 当看到alloc/retain/copy时 需要写对应release/autorelease 引用记数加减平衡
* 看不到 不管
*/
/**
* 所有权问题
* 哪个对象对引用计数进行+1 就由哪个对象进行相应的-1
* 获得所有权->让引用计数+1
*/
Person *dawa = [[Person alloc] init];// 0 -> 1
Person *nanshen = [dawa retain];// 1 -> 2
Person *xiaohua = [dawa retain];// 2 -> 3
Person *marry = dawa;// 3 -> 3 没有所有权
[dawa release];
[nanshen release];
[xiaohua release];
// 遍历构造器
@autoreleasepool {
// 正常创建对象
Person *t1 = [[Person alloc]initWithName:@"ss" age:12];
// 内存管理
[t1 release];
// 遍历构造器 不需要在外部管理内存
Person *t2 = [Person personWithName:@"qq" age:23];
}
/**
* 属性内存管理
* retain/copy 类型的属性 使用setter方法赋值时 会对赋值的对象引用计数 +1 (让对象对赋值的内容有所有权) 防止提前被释放
* 举例: p.name = name name会被引用计数 +1
* retain/copy类型属性 需要在dealloc方法中 让对应的成员变量release
* 举例: [_name release];
*/
// 字符串的内存管理
// 不可变字符串永远为 -1
NSString *str = @"123";
NSLog(@"~~~%ld", str.retainCount);
// 可变字符串 根正常对象一样
NSMutableArray *mStr = [str mutableCopy];
NSLog(@"!!%ld", mStr.retainCount);
// 容器内存管理
NSMutableArray *mArr = [NSMutableArray array];
Person *ppp = [[Person alloc] init];
// 对象加入collection时 集合会对加入的对象拥有一次所有权 让引用对象 +1
[mArr addObject:ppp];
[mArr addObject:ppp];
// 对象移除时 引用计数 -1
[mArr removeObject:ppp];
// 数组销毁时对数组中所有元素逐一 -1
// [mArr release];
NSLog(@"%lu %lu", ppp.retainCount, mArr.retainCount);
return 0;
}
//
// Test.h
// OC_内存管理
//
// Created by YIem on 15/12/3.
// Copyright (c) 2015年 www.yiem.net YIem博客. All rights reserved.
//
import <Foundation/Foundation.h>
@interface Test : NSObject
@property (nonatomic, copy)
NSString *a;
@property (nonatomic, retain)
NSArray *b;
@property (nonatomic, retain)
NSMutableArray *c;
@property (nonatomic, retain)
NSDictionary *d;
@property (nonatomic, retain)
NSMutableDictionary *e;
@property (nonatomic, assign)
NSMutableDictionary *f ;
@end
//
// Test.m
// OC_内存管理
//
// Created by YIem on 15/12/3.
// Copyright (c) 2015年 www.yiem.net YIem博客. All rights reserved.
//
import "Test.h"
@implementation Test
(void)dealloc
{[_a release]; [_b release]; [_c release]; [_d release]; [_e release]; [super dealloc];
}
@end
//
// Person.h
// OC_内存管理
//
// Created by YIem on 15/12/3.
// Copyright (c) 2015年 www.yiem.net YIem博客. All rights reserved.
//
import <Foundation/Foundation.h>
// <NSCopying> 协议 提供一些需要实现的方法声明
@interface Person : NSObject<NSCopying>
@property (nonatomic, copy)
NSString *name;
@property (nonatomic, assign)
NSInteger age;
/// 初始化
(instancetype)initWithName:(NSString *)name
age:(NSInteger)age;
// 遍历构造器
(instancetype)personWithName:(NSString *)name
age:(NSInteger)age;
@end
//
// Person.m
// OC_内存管理
//
// Created by YIem on 15/12/3.
// Copyright (c) 2015年 www.yiem.net YIem博客. All rights reserved.
//
import "Person.h"
@implementation Person
// dealloc 方法对应alloc 负责销毁/回收内存
// 一定不要手动对应该方法!!!!
// 当该类的引用记数减为0时 系统自动调用该方法 销毁对象所在堆内存
//
(void)dealloc
{// retain/copy类型的属性 要给对应的成员变量release [_name release]; NSLog(@"对象%@被销毁", self); [super dealloc];
}
// 使用copy时 首先签订NSCopying 协议 得到copyWithZone:方法声明 实现方法
- (id)copyWithZone:(NSZone *)zone
{
// 拷贝缓冲池
Person *p = [[Person allocWithZone:zone] init];
// 将源内容复制一份
p.name = self.name;
p.age = self.age;
return p;}
(instancetype)initWithName:(NSString *)name age:(NSInteger)age
{
self = [super self];
if (self) {self.name = name; self.age = age;
}
return self;
}- (instancetype)personWithName:(NSString *)name age:(NSInteger)age
{
Person *p = [[Person alloc] initWithName:name age:age];
// 遍历构造器 使用autorelease 对alloc的引用计数 延时-1
return [p autorelease];}
@end