iOS OC08,09_内存管理
//管理内存有三种方式,
//1.是垃圾回收,java常见的管理内存的方法,系统来检測对象是否被使用,是否被释放
//2.MRC手动管理引用计数,iOS管理内存的方式,程序猿通过手动的方式来管理对象是否被释放
//3.ARC自己主动管理引用计数,基于MRC,系统自己主动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯
//
// Girl.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import <Foundation/Foundation.h>
//1.声明协议
@protocol GirlDelegate <NSObject>
@required
-(void)married;
@optional
-(void)cook;
@end
@interface Girl : NSObject
//2.声明代理人属性
@property(nonatomic,assign)id<GirlDelegate>delegate;
-(void)getMarry;
@end
//
// Girl.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import "Girl.h"
@implementation Girl
-(void)getMarry{
[self.delegate cook];
}
@end
//
// Boy.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Girl.h"
@interface Boy : NSObject<GirlDelegate,NSCopying>
-(void)dealloc;
+(Boy*)boy;
@property(nonatomic,retain)NSString *name;
@property(nonatomic,copy)NSString *hobby;
@property(nonatomic,retain)Girl *girls;
//自己定义的初始化方法
-(instancetype)initWithName:(NSString *)name
hobby:(NSString *)hobby;
+(Boy *)boyWithName:(NSString *)name
hobby:(NSString *)hobby;
@end
//
// Boy.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import "Boy.h"
@implementation Boy
-(void)cook{
NSLog(@"做饭吃");
}
-(void)dealloc{
NSLog(@"对象被释放了");
//把成员变量全部+1操作全部减去
[_name release];
[_girls release];
[_hobby release];
[super dealloc];
}
+(Boy*)boy{
Boy *b=[[Boy alloc] init];
return [b autorelease];
}
//id是void *
//id是泛型指针,能够用在不论什么方法中,可是instancetype代表实例类型,用在自己定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
//-(instancetype)init{
// Boy *b=[[Boy alloc] init];
// return [b autorelease];
//}
- (id)copyWithZone:(NSZone *)zone{
Boy *b=[Boy allocWithZone:zone];
b.hobby=_hobby;
b.name=_name;
return b;
}
-(instancetype)initWithName:(NSString *)name
hobby:(NSString *)hobby{
[super self];
if (self) {
self.name=name; //从直接赋值变成方法赋值
_hobby=hobby;
}return self;
}
+(Boy *)boyWithName:(NSString *)name
hobby:(NSString *)hobby{
Boy *b=[[Boy alloc] initWithName:name hobby:hobby];
//写便利构造器最后别忘了autorelease
return [b autorelease];
}
-(void)setName:(NSString *)name{
if(_name!=name);
[_name release];
_name=[name retain];
}
@end
对象被创建出来之后他的引用计数retainCount就变成1
Boy *boy=[[Boy alloc] init];
NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 17:47:40.331 OC08,09_内存管理[1562:152231] 1
//对对象的引用计数进行+1的操作
// //retain:对对象的引用计数进行+1
Boy *boy=[[Boy alloc] init];
NSLog(@"%ld",boy.retainCount);
[boy retain];
NSLog(@"%ld",boy.retainCount);
[boy retain];
[boy retain];
NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 17:50:13.304 OC08,09_内存管理[1571:153537] 1
2015-07-27 17:50:13.305 OC08,09_内存管理[1571:153537] 2
2015-07-27 17:50:13.305 OC08,09_内存管理[1571:153537] 4
//release:对对象的引用计数进行-1的操作
[boy release];
NSLog(@"%ld",boy.retainCount);
[boy release];
[boy release];
[boy release];
NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 17:54:44.714 OC08,09_内存管理[1580:155505] 1
2015-07-27 17:54:44.715 OC08,09_内存管理[1580:155505] 对象被释放了
2015-07-27 17:54:44.715 OC08,09_内存管理[1580:155505] 1
凝视
// //假设多次对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题(+1次数小于-1次数)
// //[boy release];
// //当对象的引用计数1->0时,会自己主动调用dealloc方法,dealloc才是相应对象释放的方法
//当对象调用release的时候,他的引用计数是1,这个对象就不再对他的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在訪问对象引用计数还是1
几个不同类型retain值
NSArray *arr=@[@"1",@"2",@"3",@"4"];
NSLog(@"%ld",arr.retainCount);
NSString *str=@"1111";
NSLog(@"%ld",str.retainCount);
NSMutableString *str2=[NSMutableString stringWithString:@"111111"];
NSLog(@"%ld",str2.retainCount);
NSDictionary *dic=@{@"1":@"2",@"3":@"4"};
NSLog(@"%ld",dic.retainCount);
NSLog(@"%p",str);
NSLog(@"%p",str2);
结果
2015-07-27 17:56:31.134 OC08,09_内存管理[1587:156279] 1
2015-07-27 17:56:31.134 OC08,09_内存管理[1587:156279] -1
2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 1
2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 1
2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 0x100002130
2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 0x100112ac0
凝视
NSString 的对象在全局静态区,他的引用计数是-1,代表正整数的最大值,其它的对象都在堆区,
Boy *boy=[[Boy alloc] init];
[boy retain];
[boy retain];
NSLog(@"%ld",boy.retainCount);
//release立即会把对象的引用计数-1,可是autorelease会延迟对对象的计数-1
[boy release];
NSLog(@"%ld",boy.retainCount);
[boy autorelease];
NSLog(@"%ld",boy.retainCount);
//自己主动释放池
//仅仅要对象用autorelease释放会把对象放入到系统的自己主动释放池中,等出了池子范围,对象引用计数自己主动-1,这个相当于java的垃圾回收,对象释放由系统来管理
@autoreleasepool {
[boy autorelease];
NSLog(@"%ld",boy.retainCount);
}NSLog(@"%ld",boy.retainCount);
结果
2015-07-27 19:00:44.667 OC08,09_内存管理[1602:162429] 3
2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2
2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2
2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2
2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 1
// 内存管理原则:加多少减多少,加减做到平衡,减多了过度释放,降低了没有得到释放
//对象的全部权:拥有全部权的对象能够对他进行release
Boy *b=[Boy boy];
[b retain];
NSLog(@"%ld",b.retainCount);
[b release];
结果
2015-07-27 19:05:11.838 OC08,09_内存管理[1610:164027] 2
//便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建对象不须要对内存进行管理
NSArray *arr1=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSArray *arr2=[NSArray arrayWithObjects:@"1",@"2",nil];
[arr1 release];
NSArray *arr=@[@"1",@"2",@"3",@"4"];
NSArray *newArr=[NSArray arrayWithArray:arr];
NSLog(@"%@",newArr);
NSLog(@"%ld",arr.retainCount);
NSLog(@"%ld",newArr.retainCount);
结果
2015-07-27 19:07:04.008 OC08,09_内存管理[1624:164855] (
1,
2,
3,
4
)
2015-07-27 19:07:04.009 OC08,09_内存管理[1624:164855] 1
2015-07-27 19:07:04.010 OC08,09_内存管理[1624:164855] 1
//把一个不可变的变成可变的
NSArray *arr=@[@"1",@"2",@"3",@"4"];
NSMutableArray *arr1=[NSMutableArray arrayWithArray:arr];
NSMutableArray *arr2=[arr mutableCopy];
[arr2 addObject:@"5"];
NSLog(@"%@",arr2);
NSDictionary *dic=@{@"1":@"2",@"3":@"4"};
NSMutableDictionary *dic1=[dic mutableCopy];
NSLog(@"%@",dic1);
结果
2015-07-27 19:08:34.111 OC08,09_内存管理[1633:165509] (
1,
2,
3,
4,
5
)
2015-07-27 19:08:34.112 OC08,09_内存管理[1633:165509] {
1 = 2;
3 = 4;
}
凝视
//系统的类要是实现copy功能,必须先签订拷贝NSCopying协议,然后实现相应的方法
//不可变的数组字典能够通过mutableCopy转换成可变的数组字典
//mutableCopy出来的对象可变,copy是不可变的
举例
Girl Boy文件
//
// Girl.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import <Foundation/Foundation.h>
//1.声明协议
@protocol GirlDelegate <NSObject>
@required
-(void)married;
@optional
-(void)cook;
@end
@interface Girl : NSObject
//2.声明代理人属性
@property(nonatomic,assign)id<GirlDelegate>delegate;
-(void)getMarry;
@end
//
// Girl.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import "Girl.h"
@implementation Girl
-(void)getMarry{
[self.delegate cook];
}
@end
//
// Boy.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Girl.h"
@interface Boy : NSObject<GirlDelegate,NSCopying>
-(void)dealloc;
+(Boy*)boy;
@property(nonatomic,retain)NSString *name;
@property(nonatomic,copy)NSString *hobby;
@property(nonatomic,retain)Girl *girls;
//自己定义的初始化方法
-(instancetype)initWithName:(NSString *)name
hobby:(NSString *)hobby;
+(Boy *)boyWithName:(NSString *)name
hobby:(NSString *)hobby;
@end
//
// Boy.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import "Boy.h"
@implementation Boy
-(void)cook{
NSLog(@"做饭吃");
}
-(void)dealloc{
NSLog(@"对象被释放了");
//把成员变量全部+1操作全部减去
[_name release];
[_girls release];
[_hobby release];
[super dealloc];
}
+(Boy*)boy{
Boy *b=[[Boy alloc] init];
return [b autorelease];
}
//id是void *
//id是泛型指针,能够用在不论什么方法中,可是instancetype代表实例类型,用在自己定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
//-(instancetype)init{
// Boy *b=[[Boy alloc] init];
// return [b autorelease];
//}
- (id)copyWithZone:(NSZone *)zone{
Boy *b=[Boy allocWithZone:zone];
b.hobby=_hobby;
b.name=_name;
return b;
}
-(instancetype)initWithName:(NSString *)name
hobby:(NSString *)hobby{
[super self];
if (self) {
self.name=name; //从直接赋值变成方法赋值
_hobby=hobby;
}return self;
}
+(Boy *)boyWithName:(NSString *)name
hobby:(NSString *)hobby{
Boy *b=[[Boy alloc] initWithName:name hobby:hobby];
//写便利构造器最后别忘了autorelease
return [b autorelease];
}
-(void)setName:(NSString *)name{
if(_name!=name);
[_name release];
_name=[name retain];
}
@end
执行
//Boy类使用Copy的方法
Boy *boy=[Boy boyWithName:@"张阳阳" hobby:@"玩"];
Boy *newBoy=[boy copy];
NSLog(@"%@",newBoy.name);
//假设自己的类想要实现copy功能,就必须先签订NSCopying协议,然后实现相应的协议方法,initWithZone,之后就能够使用copy的功能
NSLog(@"%ld",boy.retainCount);
NSLog(@"%ld",newBoy.retainCount);
结果
2015-07-27 19:13:02.102 OC08,09_内存管理[1644:168242] 张阳阳
2015-07-27 19:14:15.390 OC08,09_内存管理[1653:168927] 1
2015-07-27 19:14:15.390 OC08,09_内存管理[1653:168927] 1
Boy *boy1=[[Boy alloc] init];
[boy1 retain];
[boy1 retain];
NSLog(@"%ld",boy1.retainCount);
NSMutableArray *arr=[NSMutableArray arrayWithObjects:boy1, nil];
NSLog(@"%ld",[arr[0] retainCount]);
结果
2015-07-27 19:14:52.821 OC08,09_内存管理[1660:169279] 3
2015-07-27 19:14:52.822 OC08,09_内存管理[1660:169279] 4
凝视
// 当对象放入到容器Array或者字典中,对面会被容器进行一次持有,就是retain一次,他的引用计数会+1,主要是为了防止空指针的问题
// //等对象从容器移除掉之后,相应的会-1
Boy *b=[[Boy alloc] init];
Girl *girl=[[Girl alloc]init];
b.girls=girl;
NSLog(@"%ld",girl.retainCount);
Girl *girl2=[[Girl alloc] init];
b.girls=girl2;
NSLog(@"%ld",girl.retainCount);
结果
2015-07-27 19:16:00.235 OC08,09_内存管理[1667:169909] 2
2015-07-27 19:16:00.236 OC08,09_内存管理[1667:169909] 1
一个完整的类写法
//
// Person.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(nonatomic,retain)NSMutableArray *arr;
@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;
-(id)initWithName:(NSString *)name
age:(NSInteger)age;
+(Person *)personWithName:(NSString *)name
age:(NSInteger)age;
@end
//
// Person.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 zhozhicheng. All rights reserved.
//
#import "Person.h"
@implementation Person
-(id)initWithName:(NSString *)name
age:(NSInteger)age{
self=[super init];
if (self) {
self.name=name;
self.age=age;
//对象创建之后,里面的数组也会创建好,不用在外面进行创建,避免由于忘了,造成问题
self.arr=[NSMutableArray array];
}return self;
}
+(Person *)personWithName:(NSString *)name
age:(NSInteger)age{
Person *per=[[Person alloc] initWithName:name age:age];
return [per autorelease];
}
-(void)dealloc{
[_arr release];
[_name release];
//age是栈区的,我们操作的是堆区
}
@end
Person *per=[[Person alloc] initWithName:@"张阳阳" age:20];
[per.arr addObject:@"1" ];
NSLog(@"%@",per.arr);
结果
2015-07-27 19:18:09.427 OC08,09_内存管理[1675:171354] (
1
)
iOS OC08,09_内存管理的更多相关文章
- iOS夯实:内存管理
iOS夯实:内存管理 文章转自 内存管理 最近的学习计划是将iOS的机制原理好好重新打磨学习一下,总结和加入自己的思考. 有不正确的地方,多多指正. 目录: 基本信息 旧时代的细节 新时代 基本信息 ...
- IOS开发的内存管理
关于IOS开发的内存管理的文章已经很多了,因此系统的知识点就不写了,这里我写点平时工作遇到的疑问以及解答做个总结吧,相信也会有人遇到相同的疑问呢,欢迎学习IOS的朋友请加ios技术交流群:190956 ...
- IOS开发小记-内存管理
关于IOS开发的内存管理的文章已经很多了,因此系统的知识点就不写了,这里我写点平时工作遇到的疑问以及解答做个总结吧,相信也会有人遇到相同的疑问呢,欢迎学习IOS的朋友请加ios技术交流群:190956 ...
- [转载]对iOS开发中内存管理的一点总结与理解
对iOS开发中内存管理的一点总结与理解 做iOS开发也已经有两年的时间,觉得有必要沉下心去整理一些东西了,特别是一些基础的东西,虽然现在有ARC这种东西,但是我一直也没有去用过,个人觉得对内存操作 ...
- iOS开发ARC内存管理技术要点
本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇 ...
- iOS MRC ARC 内存管理
转自:http://www.jianshu.com/p/48665652e4e4 1. 什么是内存管理 程序在运行的过程中通常通过以下行为,来增加程序的的内存占用 创建一个OC对象 定义一个变量 调用 ...
- iOS开发ARC内存管理
本文的主要内容: ARC的本质 ARC的开启与关闭 ARC的修饰符 ARC与Block ARC与Toll-Free Bridging ARC的本质 ARC是编译器(时)特性,而不是运行时特性,更不是垃 ...
- iOS另类的内存管理
iOS的内存管理算是老生常谈的问题了,我们写iOS的时候无时无刻不在涉及到内存管理.从开始的MRR(manual retain-release)到后来ARC(Automatic Reference C ...
- IOS开发之内存管理--dealloc该写些什么
在非ARC开发环境中,dealloc是类释放前,清理内存的最后机会.到底那些变量和属性该释放呢,一些特殊的类(nstimer,observer)该怎么释放.需要注意的是不释放会引起内存泄露,过度释放也 ...
随机推荐
- noip 2010 三国游戏
三国游戏 三国游戏 描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有N 位武将(N为偶数且不小于4),任 ...
- 自定义View Draw过程(4)
目录 目录 1. 知识基础 具体请看我写的另外一篇文章:自定义View基础 - 最易懂的自定义View原理系列 2. draw过程作用 绘制View视图 3. draw过程详解 同measure.la ...
- 今天写页面,将.net也使用了语义法规来判断。做法来源是.net ado.net的类型判断 Infertype。一样的原理
做了一个封装,使页面更容易维护一些.主要是两个方法,如下所示: private void BindModule(Action<Repeater, string> bindSingRpt) ...
- DataTable 去重合并
//合并 dt.Merge(dt2); //去重 dt = dt.AsDataView().ToTable(true);
- 孙鑫 VC++深入详解第14课——TCP通信/UDP通信(转)
原文转自 http://blog.csdn.net/supersonico/article/details/18900319 一.用VC++来编写TCP 服务器/客户端的简单程序. 注意事项: 1.要 ...
- 使用 Python 开始你的机器学习之旅【转】
转自:https://linux.cn/article-8582-1.html 编译自:https://opensource.com/article/17/5/python-machine-learn ...
- WCF使用小例子
using System.Runtime.Serialization; using System.ServiceModel; using MySpace; using System.ServiceMo ...
- 使用jquery实现省市二级列表
这里讲用到 jquery 的 each 遍历方法 追加 节点或元素方法 append appendTO 以及 remove 清除节点 <script> $(function( ...
- BZOJ1588 [HNOI2002]营业额统计 splay模板
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 16189 Solved: 6482 [Submit][S ...
- HDU 1045 Fire Net(搜索剪枝)
http://acm.split.hdu.edu.cn/showproblem.php?pid=1045 http://acm.hdu.edu.cn/showproblem.php?pid=1045 ...