您的位置:首页 > 移动开发 > IOS开发

IOS开发核心语言0bjective C

2015-11-18 09:54 218 查看
本分享是面向有意向从事iOS开发的伙伴及苹果产品的发烧友,亦或是已经从事了iOS的开发者,想进一步提升者。如果您对iOS开发有极高的兴趣,可以与我一起探讨iOS开发,一起学习,共同进步。


C和OC对比

OC中主要开发在什么平台上的应用程序?

答:可以使用OC开发Mac OS X平台和iOS平台的应用程序

OC中新增关键字大部分是以什么开头?

答:OC中新增关键字大部分是以@开头

OC中新增加了那些数据类型?

答:Block类型

指针类型(Class, id类型)

空类型

特殊类型(SEL, nil)

面向对象特性是什么?

答:继承性,封装性,多态性

import和#include有什么区别?

答:import 的功能和 include一样, 是将右边的文件拷贝到当前import的位置.为了降低程序员的负担, 防止重复导入, 避免程序员去书写 头文件卫士, 那么OC给出来一个新的预处理指令import

import优点: 会自动防止重复拷贝

printf和NSLog有什么区别?

答: NSLog会自动换行

NSLog在输出内容时会附加一些系统信息

NSLog和printf接收的参数不一样

Foundation有什么作用?

答:Foundation.h我们称之为主头文件, 主头文件中又拷贝了该工具箱中所有工具的头文件, 我们只需要导入主头文件就可以使用该工具箱中所有的工具, 避免了每次使用都要导入一个对应的头文件


面向对象基本概念

什么是面向对象?

答:对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。

面向对象和面向过程的区别?

答:

1>面向对象是相对面向过程而言

2>面向对象和面向过程都是一种思想

面向过程

强调的是功能行为

关注的是解决问题需要哪些步骤

面向对象

将功能封装进对象,强调具备了功能的对象

关注的是解决问题需要哪些对象


类与对象

什么是对象?

答:对象是人们要进行研究的任何事物,从最简单的整数到复杂的飞机等均可看作对象,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。

什么是类?

答:具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。

类由几部分组成?

答: 类(Class) 一个类由3个部分构成

类的名称:类名

类的属性:一组包含数据的属性

类的方法:允许对属性中包含的数据进行操作的方法

怎么来定义一个类?书写类的格式

答:定义类要分为两部分: 声明和实现

类的声明格式

@interface 类名 : 父类名(NSObject)

{

定义实例变量(成员变量,属性)

}

方法的声明

@end

类的实现格式

@implementation 类名

方法的具体实现

@end;

5.OC中属性写在类中哪个位置?

答:OC类声明中属性只能在写@interface和@end之间的{}中

6.如何通过类创建对象?书写创建对象格式

答: 创建对象格式:

类名 *指针名 = [类名 new];

7.实例化对象调用哪个方法?实例化对象做了哪3件事?

答:实例化对象调用类方法new

1.给对象分配存储空间

2.初始化类中的实力变量

3.返回对象内存地址

8.如何访问对象中的属性?

答:使用指针访问

格式: 指针名->_属性名;


OC方法

方法和函数的区别?

答:

1)OC中的行为和C语言中的函数一样, 都是用来保存一段特定功能的代码

C语言中定义一个函数, 分为声明和实现, 声明写在.h中, 实现写在.c中

OC中定义一个方法, 也分为声明和实现, 声明写在@interface中, 实现写在@implementation

C语言的函数分为两种: 内部函数和外部函数

OC中的方法也分为两种; 类方法和对象方法

怎么声明和实现无参无返回值方法的?调用方法的格式?(书写格式)

答:

方法的声明格式:

(返回值类型)方法名;

方法的实现格式:

(返回值类型)方法名{

}

调用方法格式:

[对象名 方法名];

或者 [类名 方法名];

小括号在OC方法中有什么用法?

答:OC方法中的()有特殊的用途, OC方法中的()是用来扩住数据类型的

有参数方法格式是怎样?

带一个参数

方法声明

·- (返回值类型)方法名:(参数类型)参数名;

方法实现

- (返回值类型)方法名:(参数类型)参数名{

}

带多个参数

方法声明

- (返回值类型)方法名1:(参数类型)参数名1 方法名2:(参数类型)参数名2;

- (返回值类型)方法名1:(参数类型)参数名1 and方法名2:(参数类型)参数名

- (返回值类型)方法名1:(参数类型)参数名1 :(参数类型)参数名2;

方法实现

- (返回值类型)方法名1:(参数类型)参数名1 方法名2:(参数类型)参数名2{

}


OC类方法

类方法和对象方法的区别?

答:

0). 对象方法以-开头

类方法以+开头

1). 对象方法必须用对象调用

类方法必须用类来调用

2).对象方法中可以直接访问属性(成员变量)

类方法中不可以直接访问属性(成员变量)

3). 类方法和对象方法可以进行相互调用(展示代码)

类方法的应用场景?

答:

类方法一般用于定义工具方法

字符串查找

文件操作

数据库操作

isa是什么数据类型?

答: 类的第0个属性并不是我们编写的_age, 而是一个叫做isa的属性

isa是对象中的隐藏指针,指向创建这个对象的类,占8个字节


方法和函数的区别

函数和方法的区别?

答:

1).函数属于整个文件, 方法属于某一个类

方法如果离开类就不行

2).函数可以直接调用, 方法必须用对象或者类来调用

注意: 虽然函数属于整个文件, 但是如果把函数写在类的声明中会不识别

3).不能把函数当做方法来调用, 也不能把方法当做函数来调用

方法有哪些的注意点?

答:

方法可以没有声明只有实现

方法可以只有声明没有实现, 编译不会报错, 但是运行会报错

如果方法只有声明没有实现, 那么运行时会报:

reason: ‘+[Person demo]: unrecognized selector sent to class 0x100001140’

发送了一个不能识别的消息, 在Person类中没有+开头的demo方法

reason: ‘-[Person test]: unrecognized selector sent to instance 0x100400000’

常见的错误有哪些?

1.只有类的声明,没有类的实现

2.漏了@end

@interface和@implementation嵌套

4.成员变量没有写在括号里面

5.方法的声明写在了大括号里面

6.成员变量不能在{}中进行初始化、不能被直接拿出去访问

7.方法不能当做函数一样调用

8.OC方法只能声明在@interface和@end之间,只能实现在@implementation和@end之间。也就是说OC方法不能独立于类存在

9.C函数不属于类,跟类没有联系,C函数只归定义函数的文件所有

10.C函数不能访问OC对象的成员

11.低级错误:方法有声明,但是实现的时候写成了函数

12.OC可以没有@interface同样可以定义一个类


多文件开发

为什么要使用多文件?

答:

一个iOS项目可能会有多个人开发,如果多个人同时修改一个文件,那么就很可能会产生冲突,比如这个增加一个方法,那个人把这方法删掉了。另外就是当把多个人写功能合并起来的时候,也非常困难,写到一个文件中,无法顺畅的进行团队合作

OC中如何进行多文件开发?

答:

在工作中,通常把不同的类放到不同的文件中,每个类的声明和实现分开

声明写在.h头文件中,

实现写在相应的.m文件中去,

类名是什么,文件名就是什么

使用多文件开发有什么好处?

答:

显著提高团队协作的效率

提高程序的开发速度

提高程序的可维护性

提高代码的可读性


面向对象特性

:面向对象三大特性有哪些?

答:继承性,封装性,多态性

什么是封装?封装的好处?封装的规范?

答:

封装: 屏蔽内部实现的细节, 仅仅对外提供共有的方法/接口

好处: 保证数据的安全性,将变化隔离

规范: 一般情况下不会对外直接暴露成员变量, 都会提供一些共有的方法进行赋值

成员变量都需要封装起来

为什么要进行封装?

答:一个类把自己的成员变量暴露给外部的时候,那么该类就失去对该成员变量的管理权,别人可以任意的修改你的成员变量。


geeter-setter方法

什么是setter方法?sett方法的书写格式?

答:setter方法就是给成员变量赋值的方法

格式:

(1) setter方法一定是对象方法

(2) 一定没有返回值

(3) 一定以set开头, 并且set后面跟上需要设置的成员变量的名称去掉下划线, 并且首字母大写

(4) 一定有参数, 参数类型一定和需要设置的成员变量的类型一致, 并且参数名称就是成员变量的名称去掉下划线

getter方法就是获取成员变量值的方法

格式:

(1) getter方法一定是对象方法

(2)一定有返回值, 而且返回值一定和获取的成员变量的类型一致

(3)方法名称就是获取的成员变量的名称去掉下划线

(4) 一定没有参数

成员变量以下划线开头有什么好处?

答:

1.用于区分局部变量/全局变量/形参

2.方便程序编码, 提高编码效率

解释一下什么是只读属性?什么是只写属性?可读可写的属性?私有属性?

答:

一个属性可以只有getter方法, 没有setter方法, 这种属性我们称之为只读属性

一个属性也可以只有setter方法, 没有getter方法, 这种属性我们称之为只写属性

如果既有setter方法又有getter方法, 那么这种属性我们称之为可读可写的属性

一个属性也可以没有getter和setter, 这种属性我们称之为私有属性


点语法和self关键字

什么是点语法?点语法的本质?

答:如果给属性提供了getter和setter方法, 那么访问属性就又多了一种访问方式 , 点语法.

点语法的本质是调用了一个类的setter和getter方法

如何使用点语法?

答:

点语法是一个编译器的特性, 会在程序翻译成二进制的时候将.语法自动转换为setter和getter方法

如果点语法在=号的左边, 那么编译器会自动转换为setter方法

如果点语法在=号的右边, 或者没有等号, 那么编译器就会自动转换为getter方法

点语法注意事项?

答:点语法一般用于给成员变量赋值, 如果不是给成员变量赋值一般情况下不建议使用, 但是也可以使用

什么是成员变量?什么是对象方法?什么是类方法?

答:

成员变量:

成员变量是一个实例对象的具体状态特征,并且这些状态特征是可以改变的,如张三的年龄,身高,体重等

对象方法:

一个实例对象的行为,比如张三具有吃的行为,张三做出这样行为的时候,有可能会影响,自身的某些状态特征,比如张三吃可能会增加张三体重和身高。

类方法:

类方法是某个类的行为,可以直接通过类名调用;如果在类方法中需要使用某些数据,必须通过参数传入;类方法不能访问成员变量。

如何使用self?

如果self在对象方法中, 那么self就代表调用当前对象方法的那个对象

如果self在类方法中, 那么self就代表调用当前类方法的那个类

总结:

我们只用关注self在哪一个方法中 , 如果在类方法那么就代表当前类, 如果在对象方法那么就代表”当前调用该方法的对象”

self有哪些注意事项?

答:

(1)self会自动区分类方法和对象方法, 如果在类方法中使用self调用对象方法, 那么会直接报错

(2)不能在对象方法或者类方法中利用self调用当前self所在的方法

self的有哪些使用场景?

答:

可以用于在对象方法之间进行相互调用

可以用于在类方法之间进行相互调用

可以用于区分成员变量和局部变量同名的情况


继承基本概念

什么是继承?什么是父类?什么是子类?如何实现继承?

答:

1)子类获得父类的特性就是继承

2)被继承的这个类我们称之为父类/ 超类

3)继承了某个类的类我们称之为子类

4)在声明子类的时候,在子类名称后面通过:父类名称方式来实现继承

@interface 子类名称 : 父类名称

@end类

当B类继承A类, 那么B类就拥有A类所有的属性和方法(类方法/对象方法)

2.什么叫方法重写?重写后是以什么顺序调用方法的?

答:

(1)如果子类中有和父类中同名的方法, 那么我们称之为方法重写

注意: 继承中的方法调用顺序, 如果自己有就调用自己的, 如果自己没有就调用父类的

“方法的调用顺序, 先自己再父类, 如果父类中没有再爷爷类, 如果爷爷类再没有就找爷爷的爸爸类

如果一直找到NSObject类都没有找到, 那么就会报错

reason: ‘-[Iphone signalWithNumber:]: unrecognized selector sent to instance 0x1003043c0’

注意:在继承中方法可以重写, 但是属性(成员变量)不能重写

3.方法重写的使用场景?

答:使用场景:当从父类继承的某个方法不适合子类,可以在子类中重写父类的这个方法。

4.继承的条件是什么?

答:

不要以为继承可以提高代码的复用性, 以后但凡发现多个类当中有重复代码就抽取一个父类

只要满足一定的条件我们才能使用继承

条件: XXXX 是 XXX / 某某某 is a 某某某

5.继承的优点是什么?

答:

提高代码的复用性

可以让类与类之间产生关系, 正是因为继承让类与类之间产生了关系所以才有了多态

6.继承的缺点是什么?

答:

耦合性太强(依赖性太强)


super关键字

什么是super?

super是个编译器的指令符号,只是告诉编译器在执行的时候,去调谁的方法.

怎么使用super?

答:

super在类方法中, 一定会调用父类的类方法

super在对象方法中, 一定会调用父类的对象方法

可以利用super在任意方法中调用父类中的方法

super使用场景?

答:

子类重写父类的方法时想保留父类的一些行为


多态

什么是多态?程序中是怎么体现多态的?

答:

多态就是某一类事物的多种形态

在程序中如何表现:

父类指针指向子类对象

多态的条件是什么?

答:

1)有继承关系

2)子类重写父类方法

3)父类指针指向子类对象

多态的优点是什么?

答:提高了代码的扩展性,复用性

多态的注意点?

答:如果父类指针指向子类对象, 需要调用子类特有的方法, 必须先强制类型转换为子类才能调用


description方法

使用%@了打印一个对象,输出的是什么内容?%@的原理是什么?

答:%@是用来打印对象的, description方法默认返回对象的描述信息(默认实现是返回类名和对象的内存地址).

其实%@的本质是用于打印字符串.

只要利用%@打印某个对象, 系统内部默认就会调用父类的description方法

调用该方法, 该方法会返回一个字符串, 字符串的默认格式 <类的名称: 对象的地址>

重写description方法注意点?

答:如果在description方法中利用%@输出self会造成死循环

建议: 在description方法中尽量不要使用self来获取成员变量

因为如果你经常在description方法中使用self, 可能已不小心就写成了 %@, self


私有变量和私有方法

什么是私有变量?什么是私有方法?

答:

实例变量(成员变量)既可以在@interface中定义, 也可以在@implementation中定义

私有变量:

写在@implementation中的成员变量, 默认就是私有的成员变量, 并且和利用@private修饰的不太一样, 在@implementation中定义的成员变量在其它类中无法查看, 也无法访问

私有方法:

在@implementation中定义的私有变量只能在本类中访问


property和synthesize基本使用

@porperty是一个编译器指令

在Xocde4.4之前, 可以使用@porperty来代替getter/setter方法的声明

也就是说我们只需要写上@porperty就不用写getter/setter方法的声明

编译器只要看到@property,就知道我们要生成某一个属性的

getter/setter方法的声明

@propertyde格式?

答:@property 数据类型 变量名;

@synthesize是什么指令?作用是什么?

答:

synthesize是一个编译器指令, 它可以简化我们getter/setter方法的实现

@synthesize age = _age; 在给age赋值时,编译器做了哪些事?

@synthesize age = _age;

(1)在@synthesize后面的age,告诉编译器, 需要实现哪个@property生成的声明

(2)告诉@synthesize, 需要将传入的值赋值给谁和返回谁的值给调用者

如果在@synthesize后面没有告诉系统将传入的值赋值给谁, 系统默认会赋值给和@synthesize后面写得名称相同的成员变量

@synthesize age;

property增强做了哪些事?

答:

(1)从Xcode4.4以后,对@property进行了增强, 以后只要利用一个@property就可以同时生成setter/getter方法的声明和实现

(2)如果没有告诉@property要将传入的参数赋值给谁, 默认@property会将传入的属性赋值给_开头的成员变量

7.@property的使用场景?

答:

如果不想对传入的数据进行过滤, 仅仅是提供方法给外界操作成员变量, 那么就可以使用@property,并且系统会自动给我们生成一个_开头的成员变量

8.使用property增强后,什么时候要重写getter/setter方法?

答:使用property增强,只会生成最简单的getter/setter方法的声明和实现, 并不会对传入的数据进行过滤

如果想对传入的数据进行过滤, 那么我们就必须重写getter/setter方法

9.重写getter/setter方法有哪些注意点?

答:

如果重写了setter方法, 那么property就只会生成getter方法

如果重写了getter方法, 那么property就只会生成setter方法

如果同时重写了getter/setter方法, 那么property就不会自动帮我们生成私有的成员变量


property修饰符

增强@property使用修饰符后的的格式是什么?

答:

格式:

@property(属性修饰符) 数据类型 变量名称;

@property 有哪些修饰符?各有什么作用?

答:readwrite: 代表既生成getter方法 , 也生成setter方法

默认情况下 @property就是readwrite的

@property(readwrite) int age;

‘readonly: 代表只生成getter方法不生成setter方法’

可以给setter方法起别名@property(setter=tiZhong:) double weight;

可以给getter方法起别名@property(getter=isMarried) BOOL married;


静态数据类型和动态数据类型

静态数据类型的特点:

在编译时就知道变量的类型,

知道变量中有哪些属性和方法

在编译的时候就可以访问这些属性和方法,

并且如果是通过静态数据类型定义变量, 如果访问了不属于静态数据类型的属性和方法, 那么编译器就会报错

动态数据类型的特点:

在编译的时候编译器并不知道变量的真实类型, 只有在运行的时候才知道它的真实类型

并且如果通过动态数据类型定义变量, 如果访问了不属于动态数据类型的属性和方法, 编译器不会报错

id和NSObject * 的区别?

答:

NSObject *是一个静态数据类型

id 是一个动态数据类型

动态数据类型的应用场景?

答:动态类型主要用在多态, 可以减少代码量, 避免调用子类特有的方法需要强制类型转换

动态数据类型的弊端是什么?

答:由于动态数据类型可以调用任意方法, 所以有可能调用到不属于自己的方法, 而编译时又不会报错, 所以可能导致运行时的错误

判断数据类型的有哪些方法?(变量 修改为 对象)

答:为了避免动态数据类型引发的运行时的错误, 一般情况下如果使用动态数据类型保存一个对象, 在调用这个变量的方法之前会进行一次判断, 判断当前对象是否能够调用这个方法


构造方法

什么是构造方法?

答:

在OC中init开头的方法, 我们称之为构造方法

构造方法的用途?

答:

构造方法的用途: 用于初始化一个对象, 让某个对象一创建出来就拥有某些属性和值

如何实现构造方法?

答:

重写init方法, 在init方法中初始化成员变量

如何重写init方法?

答:重写init方法必须按照苹果规定的格式重写, 如果不按照规定会引发一些未知的错误

(1)必须先初始化父类, 再初始化子类

(2)必须判断父类是否初始化成功, 只有父类初始化成功才能继续初始化子类

(3)返回当前对象的地址

- (instancetype)init
{
// 初始化父类
// 只要父类初始化成功 , 就会返回对应的地址, 如果初始化失败, 就会返回nil
// nil == 0 == 假 == 没有初始化成功
self = [super init];
// 判断父类是否初始化成功
if (self != nil) {
// 初始化子类
// 设置属性的值
_age = 6;
}
// 返回地址
return self;
}

[/code]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


自定义构造方法

什么是自定义构造方法?为什么要自定义构造方法?

(1)自定义构造方法就是自定义一个init方法

(2)有时候我们需要在创建某个对象的时候,让对象的某些属性就具有值,这时候就需要传入一些参数给对象的属性,为了满足这个需求,就需要自定义构造方法

自定义构造方法的格式?

答:

(1)一定是对象方法

(2)一定返回id/instancetype

(3)方法名称一定以init开头

-(instancetype)initWithAge:(int)age;

自定义构造方法在继承中有一个原则?

答:自己的事情自己做,属于谁的属性就由谁来进行操作

父类的属性交给父类的方法来处理,子类的方法处理子类自己独有的属性

自定义构造方法在子类,如何调用的父类构造方法的?

答:子类在重写自定构造方法时,一般使用super 调用父类的构造方法,先让父类将父类的属性进行初始化

- (instancetype)initWithAge:(int)age andName:(NSString *)name andNo:(int)no
{
if (self = [super initWithAge:age andName:name]) {
_no = no;
}
return self;
}

[/code]

1
2
3
4
5
6
7


instancetype和id区别

instancetype和id区别?

答:

(1)id在编译的时候不能判断对象的真实类型

instancetype在编译的时候可以判断对象的真实类型
(2)如果init方法的返回值是instancetype, 那么将返回值赋值给一个其它的对象会报一个警告

如果是在以前, init的返回值是id, 那么将init返回的对象地址赋值给其它对象是不会报错的
(3)id可以用来定义变量, 可以作为返回值, 可以作为形参

instancetype只能用于作为返回值

instancetype 应用场景?

答:以后但凡自定义构造方法, 返回值尽量使用instancetype, 不要使用id


类工厂方法

什么是类工厂方法?

答:用于快速创建对象的类方法, 我们称之为类工厂方法

类工厂方法应用场景?

答:类工厂方法中主要用于 给对象分配存储空间和初始化这块存储空间

类工厂方法使用规范?

答:规范:

1.一定是类方法 +

2.方法名称以类的名称开头, 首字母小写

3.一定有返回值, 返回值是id/instancetype

4.在类工厂方法实现中,调用本类的构造方法,创建实例对象,并返回实例对象

自定义类工厂方法是苹果的一个规范, 一般情况下, 我们会给一个类提供自定义构造方法和自定义类工厂方法用于创建一个对象。

类工厂方法在继承中的注意点

以后但凡自定义类工厂方法, 在类工厂方法中创建对象一定要使用self来创建,一定不要使用类名来创建。


类的本质及存储细节

类的本质是什么?

答:

(1)类其实也是一个对象, 这个对象会在这个类第一次被使用的时候创建

(2)只要有了类对象, 将来就可以通过类对象来创建实例对象

(3)实例对象中有一个isa指针, 指向创建自己的类对象

(4)类对象中保存了当前对象所有的对象方法

(5)当给一个实例对象发送消息的时候, 会根据实例对象中的isa指针去对应的类对象中查找

(6)所有类对象的继承关系就是元类对象的继承关系


类的启动过程

1.load方法

“load方法调用时间:”

只要程序启动就会将所有类的代码加载到内存中, 放到代码区

“调用次数”

load方法会在当前类被加载到内存的时候调用, 有且仅会调用一次

2.initialize方法

“initialize方法调用时间:”

当当前类第一次被使用的时候就会调用(创建类对象的时候)

“调用次数”


SEL类型

SEL是什么类型?

答:

SEL类型代表着方法的签名,在类对象的方法列表中存储着该签名与方法代码的对应关系

SEL有什么作用?

答:

(1)SEL类型的第一个作用, 配合对象/类来检查对象/类中有没有实现某一个方法

(2)SEL类型的第二个作用, 配合对象/类来调用某一个SEL方法

(3)配合对象将SEL类型作为方法的形参

哪个方法是用来检验对象是否实现了某个方法?

判断实例是否实现某个对象方法

(BOOL)respondsToSelector: (SEL)selector

判断类是否实现某个类方法

(BOOL)instancesRespondToSelector:(SEL)aSelector;

哪些方法是用来调用对象中SEL类型对应的方法?

答:

让对象执行某个方法

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

[/code]

1
2
3


内存管理

什么是堆?什么是栈?

答:

栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出);

堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由系统回收,分配方式类似于链表。

什么是内存管理?

答:

所谓内存管理, 就是对内存进行管理, 涉及的操作有

分配内存 : 比如创建一个对象, 会增加内存占用

清除内存 : 比如销毁一个对象, 能减小内存占用

内存管理的本质是什么?

答:

OC对象存放于堆里面

非OC对象一般放在栈里面(栈内存会被系统自动回收)


MRC内存管理

什么是引用计数器?

答:每个OC对象都有自己的引用计数器,它是一个整数,表示有多少人正在用这个对象

引用计数器的作用?

答:

(1)当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1

(2)当对象的引用计数器为0时,对象占用的内存就会被系统回收

如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )

怎么操作引用计数器?

答:

给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身)

给对象发送一条release消息, 可以使引用计数器值-1

给对象发送retainCount消息, 可以获得当前的引用计数器值

需要注意的是: release并不代表销毁\回收对象, 仅仅是计数器-1

dealloc 方法的作用?

答:对象即将被销毁时系统会自动给对象发送一条dealloc消息 (因此, 从dealloc方法有没有被调用,就可以判断出对象是否被销毁)

重写dealloc方法有什么注意点?

答:重写dealloc方法, [super dealloc]一定要写到所有代码的最后

内存管理的原则?

答:

(1)谁创建谁release :

如果你通过alloc、new、copy或mutableCopy来创建一个对象,那么你必须调用release或autorelease

(2)谁retain谁release:

只要你调用了retain,就必须调用一次release

(3)总结:

有加就有减,曾经让对象的计数器+1,就必须在最后让对象的计数器-1

setter方法的内存管理

实现set方法内存管理有哪几步?

答:

(1)retain需要使用的对象

(2)release之前的对象

(3)只有传入的对象和之前的不同才需要release和retain
- (void)setRoom:(Room *)room
{
// 只有房间不同才需用release和retain
if (_room != room) {
// 0ffe1 != 0ffe1
// 2.将以前的房间释放掉 -1
[_room release];
// retain不仅仅会对引用计数器+1, 而且还会返回当前对象
_room = [room retain];
}
}

[/code]

1
2
3
4
5
6
7
8
9
10
11

property修饰符

1.readonly: 只会生成getter方法

readwrite: 既会生成getter也会生成setter, 默认什么都不写就是readwrite

2.getter: 可以给生成的getter方法起一个名称

setter: 可以给生成的setter方法起一个名称

3.retain: 就会自动帮我们生成getter/setter方法内存管理的代码

assign: 不会帮我们生成set方法内存管理的代码, 仅仅只会生成普通的getter/setter方法, 默认什么都不写就是assign

4.多线程

atomic :性能低(默认)

nonatomic :性能高

在iOS开发中99.99%都是写nonatomic

property修饰符 有拿几点需要注意的问题?

答:

1.相同类型的property修饰符不能同时使用

2.不同类型的property修饰符可以多个结合在一起使用, 多个之间用,号隔开

3.iOS开发中只要写上property, 那么就立刻写上nonatomic

什么是循环retain?

答:

如果A对用要拥有B对象, 而B对应又要拥有A对象, 此时会形成循环retain

解决循环retain的方法,一边用retain一边用assign


autorelease 自动释放池

什么是自动释放池?

答:

autorelease是一种支持引用计数的内存管理方式,只要给对象发送一条autorelease消息,会将对象放到一个自动释放池中,当自动释放池被销毁时,会对池子里面的所有对象做一次release操作

自动释放池的优点是什么?

答:

不用再关心对象释放的时间

不用再关心什么时候调用release

简述自动释放池的原理?

答:

autorelease实际上只是把对release的调用延迟了,对于每一个autorelease,系统只是把该 Object放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。

自动释放池有哪些注意事项?

答:

(1)在自动释放池中创建了对象, 一定要调用autorelease,才会将对象放入自动释放池中

(2)一个程序中可以创建N个自动释放池, 并且自动释放池还可以嵌套

(3)不要再自动释放池中使用比较消耗内存的对象, 占用内存比较大的对象

(4)尽量不要再自动释放池中使用循环, 特别是循环的次数非常多, 并且还非常占用内存

(5)千万不要写多次autorelease

(6)一个alloc/new对应一个autorelease或者release

自动释放池是以什么形式存储的?

答: 如果存在多个自动释放池的时候, 自动释放池是以 “栈” 的形式存储在堆区

栈的特点: 先进后出


ARC内存管理

问题1:ARC的原理是什么?

答:当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease,而作为程序猿,完全不需要担心编译器会做错(除非开发者自己错用ARC了)。

ARC有什么优点?

答:

1.完全消除了手动管理内存的烦琐, 让程序猿更加专注于app的业务

2.基本上能够避免内存泄露

3.有时还能更加快速,因为编译器还可以执行某些优化

ARC的原则是什么?什么是强指针?什么是弱指针?

答:只要还有一个强指针变量指向对象,对象就会保持在内存中

(1)强指针

默认所有指针变量都是强指针

被__strong修饰的指针

(2)弱指针

被__weak修饰的指针

ARC下@property修饰符有哪些?

答:

strong : 用于OC对象, 相当于MRC中的retain

weak : 用于OC对象, 相当于MRC中的assign

assign : 用于基本数据类型, 跟MRC中的assign一样

ARC中是怎么对对象进行内存管理的?

答:

(1)ARC下单对象内存管理

(2)ARC下,所有的指针都是强指针

(3)ARC, A对象想拥有B对象, 那么就需要用一个强指针指向B对象

(4)A对象不用B对象了, 什么都不需要做, 编译器会自动帮我们做

ARC怎么解决循环引用问题?

答:

ARC和MRC一样, 如果A拥有B, B也拥有A, 那么必须一方使用弱指针

也就是说 一端用strong ,一端用weak


Category 分类

书写Category的格式?

答:

// 分类的声明

@interface ClassName (CategoryName)

NewMethod; //在类别中添加方法

//不允许在类别中添加变量

@end

ClassName: 需要给哪个类扩充方法

CategoryName: 分类的名称

NewMethod: 扩充的方法

// 分类的实现

@implementation ClassName(CategoryName)

NewMethod

… …

@end

ClassName: 需要给哪个类扩充方法

CategoryName: 分类的名称

NewMethod: 扩充的方法

Category的作用?

答:

(1)在不改变原来的类内容的基础上,为类增加一些方法。

(2)一个庞大的类可以分模块开发,由多个人来编写,更有利于团队合作

分类,原来类或者父类中的方法调用的顺序?

答:先调用分类中的方法(最后参与编译的分类优先),再调用原来类中的方法,最后掉用父类中的方法


Extension 匿名扩展

什么是类扩展?

答:延展类别又称为扩展(Extension),Extension是Category的一个特例

类扩展格式?

答:

类扩展书写格式

@interface 类名 ()

@end

类扩展的作用是什么?

答:写在.m文件中,可以为某个类扩充一些私有的成员变量和方法


Block

什么是Block?

答:Block是iOS中一种比较特殊的数据类型,用来保存某一段代码

Block的作用?

答:Block用来保存某一段代码, 可以在恰当的时间再取出来调用

功能类似于函数和方法

Block的格式?

答:Block的格式:

返回值类型 (^block变量名)(形参列表) = ^(形参列表) {

};


协议

什么是协议?

答:其他语言有接口的概念,接口就是一堆方法的声明没有实现.

OC中没有接口的概念,OC中的接口就是协议.

协议Protocol是由一系列的方法声明组成的

书写协议的格式?

答:

格式:

@protocol 协议名称

// 方法声明列表

@end

一个类怎么遵循协议?

答:类遵守协议格式:

@interface 类名 : 父类 <协议名称1, 协议名称2,…>

@end

注意:

(1)一个类可以遵守1个或多个协议

(2)任何类只要遵守了Protocol,就相当于拥有了Protocol的所有方法声明

4.协议和继承有什么区别?

答:

(1)继承之后默认就有实现, 而protocol只有声明没有实现

(2)相同类型的类可以使用继承, 但是不同类型的类只能使用protocol

(3)protocol可以用于存储方法的声明, 可以将多个类中共同的方法抽取出来, 以后让这些类遵守协议即可

什么是基协议?

答:基协议:是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。

注意:建议每个新的协议都要遵守NSObject协议

6.协议有哪些注意事项?

答:

(1)协议只能声明方法, 不能声明属性

(2)父类遵守了某个协议, 那么子类也会自动遵守这个协议

(3)在OC中一个类可以遵守1个或多个协议

注意: OC中的类只能有一个父类, 也就是说OC只有单继承

(4)OC中的协议又可以遵守其它协议, 只要一个协议遵守了其它协议, 那么这个协议中就会自动包含其它协议的声明

7.协议中控制方法的能否实现的关键字是什么?各有什么作用?

(1)注意: 如果没有使用任何关键字修饰协议中的方法, 那么该方法默认就是required的

(2)注意:@required和@optional仅仅使用程序员之间交流, 并不能严格的控制某一个遵守该协议的类必须要实现该方法, 因为即便不是实现也不会报错, 只会报一个警告

(3)

@required

如果协议中的方法是@required的, 要求遵守协议的类实现@required所修饰的方法,如果没有实现该方法, 那么会报一个警告

(4)

@optional

如果协议中的方法是@optional的, 遵守协议的类可选择实现@optional所修饰的方法,如果没有实现该方法, 那么不会报警告



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: