//管理内存有三种方式,
//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_内存管理的更多相关文章

  1. iOS夯实:内存管理

    iOS夯实:内存管理 文章转自 内存管理 最近的学习计划是将iOS的机制原理好好重新打磨学习一下,总结和加入自己的思考. 有不正确的地方,多多指正. 目录: 基本信息 旧时代的细节 新时代 基本信息 ...

  2. IOS开发的内存管理

    关于IOS开发的内存管理的文章已经很多了,因此系统的知识点就不写了,这里我写点平时工作遇到的疑问以及解答做个总结吧,相信也会有人遇到相同的疑问呢,欢迎学习IOS的朋友请加ios技术交流群:190956 ...

  3. IOS开发小记-内存管理

    关于IOS开发的内存管理的文章已经很多了,因此系统的知识点就不写了,这里我写点平时工作遇到的疑问以及解答做个总结吧,相信也会有人遇到相同的疑问呢,欢迎学习IOS的朋友请加ios技术交流群:190956 ...

  4. [转载]对iOS开发中内存管理的一点总结与理解

    对iOS开发中内存管理的一点总结与理解   做iOS开发也已经有两年的时间,觉得有必要沉下心去整理一些东西了,特别是一些基础的东西,虽然现在有ARC这种东西,但是我一直也没有去用过,个人觉得对内存操作 ...

  5. iOS开发ARC内存管理技术要点

    本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇 ...

  6. iOS MRC ARC 内存管理

    转自:http://www.jianshu.com/p/48665652e4e4 1. 什么是内存管理 程序在运行的过程中通常通过以下行为,来增加程序的的内存占用 创建一个OC对象 定义一个变量 调用 ...

  7. iOS开发ARC内存管理

    本文的主要内容: ARC的本质 ARC的开启与关闭 ARC的修饰符 ARC与Block ARC与Toll-Free Bridging ARC的本质 ARC是编译器(时)特性,而不是运行时特性,更不是垃 ...

  8. iOS另类的内存管理

    iOS的内存管理算是老生常谈的问题了,我们写iOS的时候无时无刻不在涉及到内存管理.从开始的MRR(manual retain-release)到后来ARC(Automatic Reference C ...

  9. IOS开发之内存管理--dealloc该写些什么

    在非ARC开发环境中,dealloc是类释放前,清理内存的最后机会.到底那些变量和属性该释放呢,一些特殊的类(nstimer,observer)该怎么释放.需要注意的是不释放会引起内存泄露,过度释放也 ...

随机推荐

  1. linux--lsof

    lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以如传输控制协议 ...

  2. [bzoj3158]千钧一发——二分图+网络流

    题目 传送门 题解 很容易建立模型,如果两个点不能匹配,那么连一条边,那么问题就转化为了求一个图上的最大点权独立集. 而我们可以知道: 最大点权独立集+最小点权覆盖集=总权值. 同时最小点权覆盖在一般 ...

  3. 除了IE浏览器,其他浏览器都联不上网怎么办~转载百度经验

    百度师傅最快的到家服务,最优质的电脑清灰 百度经验:jingyan.baidu.com 有个网友遇到一个非常奇怪的上网问题,刚才始,发现QQ不能登录,后来接着发现火狐浏览器也打不开网页,刚开始,以为只 ...

  4. scrapy爬取段子

    scrapy.py 1.cmd运行scrapy shell http://www.baidu.com response.xpath('//div[@aa="bb"]') 找到需要匹 ...

  5. 推送通知iOS客户端编写实现及推送服务器端编写

    http://blog.csdn.net/tonny_guan/article/details/8963262 1.iOS客户端编程 推送通知技术在Mac OS X和iOS系统上都可以运行,我们本章主 ...

  6. 解决:eclipse 断点调试进入到class文件,无法查看变量值问题

    今天团队一小伙伴调试项目时,一不小心选错了源文件目录(maven分模块项目),选到了顶层父项目下的文件,结果调试时发现无法查看调试过程中的变量值,要解决这个问题,其实很简单,稍稍配置一下就可以了,为了 ...

  7. [译]java8新特性:函数式编程(functional programming)的优点

    Java8引入了函数式编程,他对java是一个极大的扩展.Java从此不在是一个单纯的面向对象语言,现在他同时混合了函数式编程.这是巨大的改变,需要我们调整面对对象的编程习惯,以适应这些变化. 但是为 ...

  8. Appium+python自动化21-DesiredCapabilities详解【转载】

    Appium Desired Capabilities Desired Capabilities 是由 keys 和 values 组成的 JSON 对象. 举个简单例子: { "platf ...

  9. Starting MySQL... ERROR! The server quit without updating PID file 问题解决

    今天遇到一个mysql起不来,不知为啥挂了,启动是下面的报错 Starting MySQL... ERROR! The server quit without updating PID file 后来 ...

  10. 解决Windows下网络原因Composer安装失败问题的方法

    由于Composer镜像都在国外,所以直接在官网下载Windows Installer后安装很多情况下是无法成功安装的. 解决办法: 1,将php添加到系统环境变量,并开启openssl扩展. 2,点 ...