黑马程序员——ios开发基础之OC内存管理与blocks
2015-09-18 23:19
519 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1)内存管理的范围
所有的OC对象(继承自NSObject类)
2)为什么内存管理只管理OC对象?
堆中内存不连续, 无法自动释放
3)如何对OC对象进行内存管理?
通过操作对象的"引用计数器"
2. 引用计数器
引用计数器概念
1)每个OC对象都有自己的引用计数器
2)它是一个整数(int类型, 占用4个字节)
3)从字面上, 可以理解为"对象被引用的次数"
4)也可以理解为: 它表示有多少人正在用这个对象
引用计数器的作用
1) 系统通过"引用计数器"来判断当前对象是否可以被释放
对象的"引用计数器"的操作方式
1)retain, +1
2)release, -1
3)retainCount, 获取对象引用计数器的值
3. dealloc方法
1)当对象即将被销毁, 系统自动给对象发送一条dealloc消息
2)因此, 从dealloc方法有没有被调用, 就可以判断出对象是否被销毁
3)重写了dealloc方法, 必须调用[super dealloc], 并且放在最后面调用
4)不要自己直接调用dealloc方法
重写dealloc方法,代码规范
(1) 一定要[super dealloc],而且要放到最后,意义是:先释放子类占用的空间在释放父
类占用的空间
(2)对self(当前)所拥有的的其他对象做一次release操作
-( void) dealloc{
[_car release];
[super dealloc];
}
4. 多对象内存管理
-(void)setCar:(Car*)car{
_car = car;
}
对象已经释放了,再次去使用
[car release];
[p driver]; // _car = [car retain];
给p.car 设置不同对象的时候会造成原对象内存泄露
p.car = car1;
[car1 release]; //car1 1
p.car = car2; // [_car release]; _car = [car retain];
//
p.car = car1; //car1 2
[car1 release]; // 1
p.car = car1; // if(_car != car){_car release]; _car = [car retain];}
5. @property的修饰关键字
1)控制set方法的内存管理
retain: release旧值, retain新值(用于OC对象),要配合nonatomic使用
assign: 直接赋值, 不做任何内存管理(默认, 用于非OC对象类型)
copy: release旧值, copy新值(一般用于NSString *)
2)控制是否需要生成set方法
readwrite: 同时生成set方法和get方法(默认)
readonly: 只会生成get方法
3)多线程管理
atomic: 性能低(默认)
nonatomic: 性能高(为iOS系统开发软件建议使用,为mac开发软件可以使用atomic)
4)控制set方法和get方法的名称
setter: 设置set方法的名称, 一定有个冒号:
getter: 设置get方法的名称
6. @class用法
@class
.h @class Dog
.m #import "Dog.h"
@class和#import的区别
通过@class解决循环依赖问题
7. 内存管理时的循环retain问题
解决办法: 一端用retain、一端用assign
注意: 使用了assign后, dealloc中就不需要release了
8. 对象自动释放池的使用
对于autorelease pool本身,会在如下两个条件发生时候被释放
1)手动释放Autorelease pool
2) Runloop结束后自动释放
对于autorelease pool内部的对象
在引用计数的retain == 0的时候释放。 release和autorelease pool 的 drain都会触发retain--事件。
1、autorelease使用注意
1)并不是放到自动释放池代码中,都会自动加入到自动释放池,不管这个对象是在自动释放池内还是外创建的,只要在自动释放池内写一个 [p1 autorelease];p1就会被放到自动释放池中。注意autorelease是一个方法,且只有在自动释放池中使用才有效。
2、autorelease错误用法
( 1)连续调用多次autorelease,释放池销毁时执行两次release(-1)吗
( 2) Alloc之后调用了autorelease,之后又调用了release。
9、应用:创建一个学生类,初始化年龄
10、ARC
自动引用计数,即ARC,当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease
判断准则:
只要没有强指针指向对象,对象就会被释放。
1)强指针
所有的指针默认就是强指针
强指针使用 strong 标识
2)弱指针
所有的指针默认就是强指针
弱指针使用__week 标识
循环引入的对象中其中一个对象设置为 strong 另一个设置为 weak
ARC中的@property
strong : 用于OC对象, 相当于MRC中的retain
weak : 用于OC对象, 相当于MRC中的assign
assign : 用于基本数据类型, 跟MRC中的assign一样
copy : 一般用于NSString, 跟MRC中的copy一样
在ARC情况下解决”循环retain” 的问题: @property一边用strong,一边用weak。
可执行代码,Block对象包含着一组状态数据,
这些数据在程序执行时用于对行为产生影响。
2、使用方法
1) block最简单形式
定义格式:
void (^block名)() = ^{代码块;}
使用格式:block名();
2) block带有参数的block的定义和使用
格式:
void (^block名称)(参数列表)= ^ (参数列表) { // 代码实现; }
3) 带有参数和返回值的block
格式:
返回类型 (^block名称)(参数列表)= ^ 返回类型 (参数列表) { // 代码实现; }
3、block的typedef
利用typedef定义block类型(和指向函数的指针很像)
格式:
Typedef int(^MyBlock)(int ,int);
速记符
typedef 返回值类型 (^block变量名)(参数类型列表);
4、 block访问外部变量
1)在block内部可以访问block外部的变量
2)在block内部不可以修改block外部的变量
3)给局部变量加上__block关键字,则这个局部变量可以在block内部进行修改。
5、block使用技巧及注意
1) block 结构的快速提示:inlineBlock
2) block变量用作方法的参数的时候,最好把参数类型列表部分加上 具体的形参名
第一讲 内存管理
1. 内存管理概念理解1)内存管理的范围
所有的OC对象(继承自NSObject类)
2)为什么内存管理只管理OC对象?
堆中内存不连续, 无法自动释放
3)如何对OC对象进行内存管理?
通过操作对象的"引用计数器"
2. 引用计数器
引用计数器概念
1)每个OC对象都有自己的引用计数器
2)它是一个整数(int类型, 占用4个字节)
3)从字面上, 可以理解为"对象被引用的次数"
4)也可以理解为: 它表示有多少人正在用这个对象
引用计数器的作用
1) 系统通过"引用计数器"来判断当前对象是否可以被释放
对象的"引用计数器"的操作方式
1)retain, +1
2)release, -1
3)retainCount, 获取对象引用计数器的值
3. dealloc方法
1)当对象即将被销毁, 系统自动给对象发送一条dealloc消息
2)因此, 从dealloc方法有没有被调用, 就可以判断出对象是否被销毁
3)重写了dealloc方法, 必须调用[super dealloc], 并且放在最后面调用
4)不要自己直接调用dealloc方法
重写dealloc方法,代码规范
(1) 一定要[super dealloc],而且要放到最后,意义是:先释放子类占用的空间在释放父
类占用的空间
(2)对self(当前)所拥有的的其他对象做一次release操作
-( void) dealloc{
[_car release];
[super dealloc];
}
4. 多对象内存管理
-(void)setCar:(Car*)car{
_car = car;
}
对象已经释放了,再次去使用
[car release];
[p driver]; // _car = [car retain];
给p.car 设置不同对象的时候会造成原对象内存泄露
p.car = car1;
[car1 release]; //car1 1
p.car = car2; // [_car release]; _car = [car retain];
//
p.car = car1; //car1 2
[car1 release]; // 1
p.car = car1; // if(_car != car){_car release]; _car = [car retain];}
5. @property的修饰关键字
1)控制set方法的内存管理
retain: release旧值, retain新值(用于OC对象),要配合nonatomic使用
assign: 直接赋值, 不做任何内存管理(默认, 用于非OC对象类型)
copy: release旧值, copy新值(一般用于NSString *)
2)控制是否需要生成set方法
readwrite: 同时生成set方法和get方法(默认)
readonly: 只会生成get方法
3)多线程管理
atomic: 性能低(默认)
nonatomic: 性能高(为iOS系统开发软件建议使用,为mac开发软件可以使用atomic)
4)控制set方法和get方法的名称
setter: 设置set方法的名称, 一定有个冒号:
getter: 设置get方法的名称
6. @class用法
@class
.h @class Dog
.m #import "Dog.h"
@class和#import的区别
通过@class解决循环依赖问题
7. 内存管理时的循环retain问题
解决办法: 一端用retain、一端用assign
注意: 使用了assign后, dealloc中就不需要release了
8. 对象自动释放池的使用
对于autorelease pool本身,会在如下两个条件发生时候被释放
1)手动释放Autorelease pool
2) Runloop结束后自动释放
对于autorelease pool内部的对象
在引用计数的retain == 0的时候释放。 release和autorelease pool 的 drain都会触发retain--事件。
1、autorelease使用注意
1)并不是放到自动释放池代码中,都会自动加入到自动释放池,不管这个对象是在自动释放池内还是外创建的,只要在自动释放池内写一个 [p1 autorelease];p1就会被放到自动释放池中。注意autorelease是一个方法,且只有在自动释放池中使用才有效。
2、autorelease错误用法
( 1)连续调用多次autorelease,释放池销毁时执行两次release(-1)吗
( 2) Alloc之后调用了autorelease,之后又调用了release。
9、应用:创建一个学生类,初始化年龄
student.h #import <Foundation/Foundation.h> @interface Student : NSObject @property(nonatomic,assign) int age; -(instancetype)initWithAge:(int)age; +(instancetype)studentWithAge:(int)age; @end student.m #import "Student.h" @implementation Student - (void)dealloc { NSLog(@"Student 被释放"); [super dealloc]; } //自定义构造方法 -(instancetype)initWithAge:(int)age{ if (self = [super init]) { _age = age; } return self; } //自定义初始化方法 +(instancetype)studentWithAge:(int)age{ return [[[self alloc] initWithAge:age] autorelease]; } @end main.m #import <Foundation/Foundation.h> #import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { // Student *stu = [[[Student alloc] initWithAge:10] autorelease]; Student *stu1 = [Student studentWithAge:100]; NSLog(@"age = %d",stu1.age); } return 0; }
10、ARC
自动引用计数,即ARC,当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease
判断准则:
只要没有强指针指向对象,对象就会被释放。
1)强指针
所有的指针默认就是强指针
强指针使用 strong 标识
2)弱指针
所有的指针默认就是强指针
弱指针使用__week 标识
循环引入的对象中其中一个对象设置为 strong 另一个设置为 weak
ARC中的@property
strong : 用于OC对象, 相当于MRC中的retain
weak : 用于OC对象, 相当于MRC中的assign
assign : 用于基本数据类型, 跟MRC中的assign一样
copy : 一般用于NSString, 跟MRC中的copy一样
在ARC情况下解决”循环retain” 的问题: @property一边用strong,一边用weak。
第二讲 blocks
1、block概念可执行代码,Block对象包含着一组状态数据,
这些数据在程序执行时用于对行为产生影响。
2、使用方法
1) block最简单形式
定义格式:
void (^block名)() = ^{代码块;}
使用格式:block名();
2) block带有参数的block的定义和使用
格式:
void (^block名称)(参数列表)= ^ (参数列表) { // 代码实现; }
3) 带有参数和返回值的block
格式:
返回类型 (^block名称)(参数列表)= ^ 返回类型 (参数列表) { // 代码实现; }
3、block的typedef
利用typedef定义block类型(和指向函数的指针很像)
格式:
Typedef int(^MyBlock)(int ,int);
速记符
typedef 返回值类型 (^block变量名)(参数类型列表);
4、 block访问外部变量
1)在block内部可以访问block外部的变量
2)在block内部不可以修改block外部的变量
3)给局部变量加上__block关键字,则这个局部变量可以在block内部进行修改。
5、block使用技巧及注意
1) block 结构的快速提示:inlineBlock
2) block变量用作方法的参数的时候,最好把参数类型列表部分加上 具体的形参名
相关文章推荐
- 华为面试题 输入一个n,在屏幕上输出N*N的矩阵
- 曾经的面试
- 多个div并排显示的居中问题——来自腾讯的一道面试题
- 黑马程序员--------构造方法
- 黑马程序员-------集合
- 美团面试题 输入任意表达式输出结果
- 黑马程序员——函数与数组:精打细算的年级组长的利器
- 黑马程序员-Java基础学习-IO流
- 黑马程序员-------正则表达式
- 黑马程序员-----------异常
- Android面试准备:自定义控件
- 黑马程序员-Java基础学习-正则表达式
- 黑马程序员----内部类
- 第一次面试知识点总结
- 黑马程序员-----面向对象
- 黑马程序员-----------static关键字
- java程序员
- 职场新人完全转型七大要素
- 我的求职路
- 野生程序员的故事