FoundationDAY01

来源:互联网 发布:淘宝卖鲜花资质 编辑:程序博客网 时间:2024/06/11 23:26

day 07内存管理

 

一、知识点回顾

 

1.为什么要进行内存管理?

因为移动设备的内存空间是有限的。所以每一个应用程序或游戏所占的内存也是有限的。

当应用程序使用内存过多时,系统就会发出低内存警告,这时候就需要我们回收一些内存资源。

简单的说就是回收了一些现在不使用的对象或者变量。

 

2.对象的创建和销毁

1.第一种创建对象的方式  NSObject类

+(id)alloc方法是+方法   和-(id)init方法是-方法   套写创建对象,OC中较为常见的一种。

2.第二种创建对象的方式 C++  Java风格的创建对象.

+(id)new方法

Student  *stu1 = [Student new];

3.对象的销毁

当对象的引用计数为0时 系统自动调用了

-(void)dealloc  方法来释放对象

{

[super  dealloc];    //MRC有  且写在最后。

}

 

3.对象的基本结构

每一个OC中对象都有一个引用计数器,是一个用整数表示对象被引用的次数。

简单的说就是当前有多少个指针指向这个对象。

对象创建时计数器的值为1.当计数器的值为0时  对象被销毁。

核心原理:

1.对象所有权的概念——>体现——>引用计数

 

4.引用计数器的作用

判断对象要不要回收内存的一个依据。

系统会自动判断对象的引用计数器——>值——>是不是0,如果是0值就要自动调用-(void)dealloc  析构函数

引用计数

每一个OC的对象都有自己的引用计数器,是用一个整数表示对象的被引用的次数。每个对象的内部,都有专门的        4个字节的存储空间来保存引用计数的值。

 

5.引用计数器的操作

1.MRC   手动引用计数的操作

1.retain  方法  作用使得引用计数器+1

2.release 方法 作用使得引用计数器- 1

(并不是销毁对象  也不是释放内存) 3.retainCount方法  获得当前对象的引用计数的值。

4.自动释放池 @autoreleasepool{

 

 

}

autoreleasepool 方法  作用是自动释放池中使用的一种消息,他不会立即造成对象的应用计数的- 1.

是延时释放的。当自动释放池被销毁是,才能向释放池中的每一个对象发送消息,来销毁对象。

注意:当不能确定这个对象何时被销毁时,我们通常使用autorelease但是要神勇。效率低。

 

内存管理的原则:

1.谁创建  谁释放的原则

谁 alloc   new    谁  release

2.谁retain  谁release

3.责任制原则

1>对象该释放时  没有释放。(程序员的疏忽大意)。

2>不该释放时  对象提前释放了。(程序会崩溃或无响应)。

 

2.ARC   自动引用计数的操作

你只需要创建对象即可  对象的retain操作  release操作   autorelease操作  都不能继续使用,系统自动完成

引用计数判断对象是否需要释放或自动持有。

 

注意:在重写  -(void)dealoc方法时  ARC中  不能写[super dealloc];//不让你调用

retatinCount 

 

6.内存管理中代码规范

1.只要调用了alloc方法或new方法  就必须有release或autorelease。

2.重写set方法的代码规范

1>如果是基本数据类型  NSUInteger   NSInteger  等

直接赋值

-(void)setAge:(NSUInteger)age

{

_age = age;//直接赋值表达式赋值

}

2>如果是OC对象 的set方法的重写

-(void)setStudent:(Student *)student

{

if(_student! = student)

{

//先把原来的旧的对象   释放

[_student release];

//对新对象  进行一次retain操作

_student = [student   retain];

}

}

3>-(void)dealloc  方法的代码规范

1>一定要有dealloc方法,[super  dealloc]且要放在最后。

2>如果声明了成员变量

Student   *_student;

-(void)dealloc

{

[_student  release];

[super  dealloc];

}

 

 

7.属性北村管理  @property(内存管理)属性类型   属性名

 

1.属性内存管理的相关参数

assign:作用  是直接赋值(凡是非OC对象 默认)

比如:int  char   double   long   bool   NSUInteger等

特别注意的:

MRC中使用协议委托时

@interface  委托类:NSObject

@property(nonatomic,assign)id<xxxxxx>delegate;

@end

 

协议委托中委托人的属性为什么用assign?

1.防止循环引用。

为什么用id类型?

2.id表示泛型<协议>表示类具有通用性。

协议的作用?

3.就是分散接口的作用。

 

retain的作用:释放旧值  ,retain新值(适用于OC对象)

一般用于自定义类  Student  *; Car  *;retain的是指针  不是复制对象。

copy:作用  释放旧值,复制新值。copy的对象。

1>凡是字符串类型都用copy  NSString类型   NSMutable String

2>见到Block 做属性时  用copy

遵守<NSCoping>协议的对象

总结:retain 的是指针  copy  的是对象;

 

2.属性的参数第二类   修饰set方法的

readonly:只读就表示  这个属性只是自动生成get方法

@property(readOnly)NSUInteger  age;//只有get   没有set

readwrite:系统默认   同时生成set  和  get 方法;

 

3.多线程的管理(线程安全问题)

nonatomic: 高性能,关闭了多线程,保护变量,一般默认为该选项。

atomic:低性能  很少使用  系统中默认开启atomic多线程。

 

8.内存管理中的循环引用问题以及解决方式

例子:

每个人都有一部手机,每一个手机又对应一个人。写程序时  不能两个类之间的头文件互相包含。#import “a.h

”  #import  “b.h”  这就是循环引用。

 

关键字 @class:声明的是一个类,告诉给编译器  某一个标示符@class标示符  是一个类。

 

实际开发中:

在导入一个类时  都建议使用

xxx.h 中包含一个类

@class  ClassA;

@class ClassB;

xxx.m文件中使用某一个类中得内容

#import<ClassA>

 

2.两端循环引用的解决方式(真出现循环引用的时候)

一端使用retain  另一端使用assign

注意:使用assign端  -(void)dealloc    不用再release

 

 

ARC

1.ARC的判断准则

只要没有强类型的指针指向对象  对象就会被释放。

 

2.指针的分类

1.强类型的指针:strong  默认情况下所有的指针类型都是强类型。

2.弱类型的指针:weak。

看demo

 

二、Block 块语法($3000)

1.Block封装了一个段代码,可以在任何时候执行。

2.Black可以作为函数参数或函数的返回值。

3.Block回调。

4.Block用于多线程、异步任务、集合类的便利、集合类排序动画的转场。

5.Block访问全局变量和局部变量。

6.Block反向传值。

 

2.Block块的声明

Block是苹果公司推荐使用的一种数据类型。

特点:1.效率高  在运行中保存代码。常用来封装和保存代码,一般底层函数较多。有点像函数,Block可以在

任何时候执行。

和函数的相似性:

1.都可以用来保存代码

2.都可以由返回值

3.都可以由参数

4.调用的方式相同

 

C语言中的函数指针

void(*p)(int );

void(^p)(int);

 

3.Block的标示符  ^

3.1Block块的声明

返回值类型 (^变量名)(参数类型);

3.2Block块的声明和实现写在一起

void(^myBlock)(int) = ^(int  n)

{

//块的内容

for(;;)

{

NSLog(@"Hello   World");

}

};

3.3Block块 的调用

myBlock(10);//打印十次hello world。

 

 

四、NSNumber  数字对象

 

提供的是一个OC中得Foundation 框架中的类,作用就是把C语言中得基本数据类型  int  char  float  double long bool等这些数值数据封装成一个NSNumber 数字对象的类。

NSNumber 是 NSValue的一个子类。

 

作用:数字变量——>数字对象——>在OC中使用了

 

- (id)initWithChar:(char)value;

- (id)initWithUnsignedChar:(unsigned char)value;

- (id)initWithShort:(short)value;

- (id)initWithUnsignedShort:(unsigned short)value;

- (id)initWithInt:(int)value;

- (id)initWithUnsignedInt:(unsigned int)value;

- (id)initWithLong:(long)value;

- (id)initWithUnsignedLong:(unsigned long)value;

- (id)initWithLongLong:(long long)value;

- (id)initWithUnsignedLongLong:(unsigned long long)value;

- (id)initWithFloat:(float)value;

- (id)initWithDouble:(double)value;

- (id)initWithBool:(BOOL)value;

- (id)initWithInteger:(NSInteger)value NS_AVAILABLE(10_5, 2_0);

- (id)initWithUnsignedInteger:(NSUInteger)value NS_AVAILABLE(10_5, 2_0);

 

+ (NSNumber *)numberWithChar:(char)value;

+ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;

+ (NSNumber *)numberWithShort:(short)value;

+ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;

+ (NSNumber *)numberWithInt:(int)value;

+ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;

+ (NSNumber *)numberWithLong:(long)value;

+ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;

+ (NSNumber *)numberWithLongLong:(long long)value;

+ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;

+ (NSNumber *)numberWithFloat:(float)value;

+ (NSNumber *)numberWithDouble:(double)value;

+ (NSNumber *)numberWithBool:(BOOL)value;

+ (NSNumber *)numberWithInteger:(NSInteger)value NS_AVAILABLE(10_5, 2_0);

+ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value NS_AVAILABLE(10_5, 2_0);

 

0 0
原创粉丝点击