A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

#program mark - 01 @class关键字 [掌握]

1.头文件循环引用的前提

    1.如果使用#import指令,在A类中导入B类的头文件,同时在B类中导入了A类的头文件

    2.在A类或者B类中,使用到了导入的类型

以上两点同时存在,才会出现头文件循环引用的问题


2.如何解决循环引用的问题

    1.在A类的头文件中使用#import,在B类的头文件中使用@class关键字

    2.在B类的.m文件中,使用#import导入A类的头文件,这样才能正常使用A类


3.@class

不是一个预处理指令,它的作用仅仅是声明有这样一个类,可以使用该类型

但是@class并不会拷贝类的头文件到写指令的位置,所以并不知道类中有哪些内容

在需要使用类中的内容的时候,还需要使用#import指令导入该类的头文件


4.请说出#inclue #import @class的区别

#include是一个预处理指令,会把文件内容拷贝到写指令的地方

#import是一个预处理指令,是#include的增强版,可以避免头文件的重复包含

@class是一个关键字,而不是预处理指令,作用是声明有这样一个类,但是并不会导入类的头文件


5.@class不需要拷贝文件,所以性能比#import

可以在头文件中只使用@class声明类,然后在.m中,当具体使用到某个类的时候,再去#import头文件,这样做可以提高性能

在公司中根据之前老员工的编程习惯和代码习惯来模仿就可以了



#program mark - 02 循环retain [掌握]

循环引用:在A对象中拥有B对象,在B对象中拥有A对象,如果两端都使用retain的内存管理策略,会导致A和B都无法释放,造成内存泄漏

解决方案:一端用retain,另外一端用assign.

注意:用assign的一端不要在dealloc中释放对应的成员变量


MRC中,当对象的引用计数器为0的时候,会释放对象,同时由系统调用对象的dealloc方法

引用计数器=0 -> 对象销毁 -> dealloc


#program mark - 03 自动释放池的使用 [掌握]

1.什么是自动释放池

// 有一个NSAutoreleasPool类,用来描述自动释放池


@autoreleasepool {

   

}


自动释放池就是一对大括号包裹的作用域,只不过这个作用域前面有一个@autoreleasepool修饰




2.和普通的作用域的区别

1.比普通作用于多了一个@autoreleasepool修饰符

2.自动释放能够在销毁(作用域结束)的时候,自动的对其中调用过autorelease方法的对象,发送release消息


3.作用:

防止对于使用alloc \ new 创建的对象,忘记手动调用release方法,而出现内存泄漏的问题


4.注意点

一个对象写在@autoreleasepool并不代表该对象会自动释放,还需要调用autorelease方法,把对象添加到自动释放池中,这样才会自动release


#program mark - 04 使用自动释放出的七大注意 [掌握]

1.需要通过自动释放池释放的对象,并不需要池中创建,只要保证是在当前自动释放池中调用对象的autorelease方法即可

2.autorelease并不是立刻给对象发送release消息,只是把对象添加到当前自动释放池中,当当前自动释放池销毁的时候,会自动的给对象发一条release

3.给对象发送release消息之后,对象不一定会销毁.

在MRC环境下,判断对象是否销毁,只有一个原则,就是对象的引用计数器是否为0

4.不要给对象多次调用autorelease,可能会造成野指针错误

5.自动释放池可以嵌套,对象在哪个自动释放中调用autorelease方法,那就会在该自动释放池销毁的时候,给对想发送release消息



自动释放池的最常见用法:(自动释放池存在的意义)

帮助我们在使用new或者alloc创建对象之后,不需要手动调用release


#program mark - 05 自动释放池的规范 [掌握]

1.在定义类的时候,需要定义一个和类同名的类方法,用来返回一个对象,作用就是为了快速创建一个指定值对象

2.在MRC中,只有看到new\alloc\retain的时候,才需要调用release,所有使用类方法创建的对象,不应该在外部release

3.在类方法内部返回对象之前,需要把对象添加到自动释放池中


4.规范:创建类需要提供类方法返回一个对象,而且需要在此方法内部调用autorelease方法,把对象添加到自动释放池中,苹果内部也是这样做的


#program mark - 07 微博练习 [掌握] [讲]

1.返回对象的类方法,在对象返回之前需要调用autorelease,把对象添加到自动释放池中

2.使用@class防止头文件的循环依赖

3.注意对象之间的循环retain



// 从ARC开始,对MRC的东西全都不需要了

#program mark - 08 ARC机制的概述 [掌握]

1.ARC是一个编译器特性,2011年iOS5开始出现的

编译器在编译代码的时候,会自动的在合适的位置插入内存管理的代码(release\retain\autorelease)

在ARC机制下不用使用内存管理相关的方法

release\retain\autorelease\retainCount\dealloc


2.ARC本质上是基于MRC,从根本上来说,还是需要根据引用计数器判断对象是否需要释放

但是这个过程别编译器屏蔽起来了,不需要程序员来做,所以可以认为,在ARC机制中,没有引用计数器的概念


3.ARC内存管理的原则

只要一个对象没有强指针指向,那么就会释放


4.对指针的修饰符

1.__strong修饰的指针是强指针,默认情况下只要定义一个指针变量,就是强指针

2.__weak修饰时指针是弱指针

强指针和弱指针在操作对象方法没有任何的区别

唯一的区别:作为ARC机制下,判断对象是否需要回收的标准


#program mark - 09 第一个ARC程序 [掌握]

1.Xcode6之后,默认创建的项目都是ARC环境

2.在ARC中,可以重写dealloc,但是在最后不要调用[super dealloc];


3.没有强指针指向任何对象

    1.指向对象的所有强指针在作用域结束之后被回收了

    2.指向对象的所有强指针都指向了nil


4.创建对象的时候,千万不要使用弱指针指向,没有任何意义,编译器会报警告

__weak HMPerson *p = [HMPerson new];



#program mark - 10 @property参数strong与weak [掌握]

MRC的时候

@property retain assign

ARC内存管理相关的参数


1.ARC机制下,setter方法中直接赋值即可,不需要做其它事情,所以retain没有意义

2.ARC机制下,使用@property的时候,只需要考虑它自动生成的成员变量是强指针还是弱指针

两个新的参数

strong,代表@property自动生成的私有成员变量是强指针类型的

weak,代表@property自动生成的私有成员变量是弱指针类型的


3.

在ARC机制下,如果成员变量是OC对象,大多数情况下,使用strong,有一些特殊情况需要使用weak

如果成员变量是非OC对象,使用assign



#program mark - 11 ARC机制下的循环引用 [掌握] [讲]

出现的问题:当A对象有一个属性是B对象,B对象中有一个属性是A对象,如果在两端都使用strong,那么会造成对象的循环引用,导致两个对象都无法释放

解决方案:一段使用strong,另外一端使用weak即可


MRC中因为使用reatin导致循环引用

ARC中因为使用strong导致循环引用


#program mark - 12 @property参数总结 [掌握]

strong weak retain assign


#program mark - 13 弱指针在对象被回收以后自动设置为nil [掌握]


如果在MRC中,当对象释放之后,再通过指向该对象的指针给该对象发送消息,就会造成野指针错误


使用__weak关键字的好处:

如果在ARC中,当weak指针指向的对象释放之后,会自动把该指针指向nil,避免野指针错误


#program mark - 14 MRC和ARC的兼容 [掌握]


MRC手动内存管理:手动管理对象的引用计数器 release\reatin

ARC自动内存管理:编译器会自动帮助我们管理对象的引用计数器


目前在公司中,比较主流的新的项目,肯定都是ARC的

但是可能会存在一些老的项目


老的MRC项目里面 可能会用到一些功能(第三方框架:别人写好的功能的集合)

可能会开发新的项目,可能有一些老的第三方框架,其有一个功能非常好用,但是没有推出ARC的版本


ARC和MRC混合开发的情况...


1.如果在ARC的环境下,想要正常编译MRC的代码,那么需要通过编译器参数,单独告诉编译器,包含MRC代码的.m文件不要以ARC的形式进行编译

-fno-objc-arc


2.如果在MRC的环境下,想要正常编译ARC的代码,那么需要通过编译器参数,单独告诉编译器,包含ARC代码的.m文件不要以MRC的形式进行编译

-fobjc-arc


#program mark - 15 MRC程序转换为ARC程序 [掌握]


1.可以通过Xcode的Convert功能,把MRC的项目转换成ARC的项目

2.它的做法其实就是把MRC中相关的内存管理代码去掉

3.这种方式不靠谱,可能会失败,成功率比较低,不推荐使用


总结:

MRC和ARC混合开发的解决方案

1.使用Xcode自带的转换工具,把MRC转换成ARC,但是有风险

2.使用编译器标记

3.静态库:在生成静态库的时候,就会把文件先编译好

4.条件编译:

#if !__has_feature(objc_arc)

    [array release];

#endif

可以使用条件编译,判断当前编译器的特性,如果是MRC,那么就使用内存管理的代码,如果是ARC就不使用内存管理的代码


4.Product中的工具Analyze,静态检测工具,可以根据语法检测代码是否存在问题


// 新的语法

#program mark - 16 分类的简单使用 [掌握]

1.分类是什么:

OC中特有的yufa

2.分类的作用:

将1个类分为多个模块,将类似的方法放在同一个模块中,这可以方便我们后期对类进行维护和管理

3.格式

@interface HMPerson (base)


- (void)eat;


@end


@implementation HMPerson (base)


- (void)eat {

   

}


@end



4.如果需要给一个类增加方法,有几种方式?

    1.直接修改原来的类

    2.继承,成为该类的子类

3.使用分类:在不改变原来类以及成为其子类的情况下,给该类扩展方法


5.如果在@interface使用@property,会做3件事情

    1.生成一个_开头的私有成员变量

    2.针对该成员变量生成setter和getter的声明

    3.针对该成员变量生成setter和getter的实现



6.如果在分类中使用@property会做几件事情?

只会生成setter和getter的声明,不会生成_开头的私有成员变量,以及不会生成setter和getter的实现




1 个回复

倒序浏览
很详细,收下了·~~~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马