iOS面试要点三


2、static的作用:

static 局部变量: 变量只内存分配一次,生命周期类似于全局变量,在下一次调用时维持上一次的值,作用域在函数内部;

static 全局变量:只可以被模块内所有函数访问,但不能被模块外其他函数访问;

static 函数:只可被模块内的其他函数调用;

类中 static 成员变量:属于整个类所拥有,对类的所有对象只有一份拷贝,即派生类与基类共用一个静态成员变量;

类中 static 成员函数: 属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。


3、线程与进程

进程:系统中正在运行的程序,每个进程都是独立的,一个进程奔溃不会影响其他进程,一个进程至少有一个线程;

线程:是进程的一个任务的执行,多个线程共享资源,一个线程奔溃整个进程就是奔溃。


4、堆和栈的区别

管理方式:对于栈来讲,是由编译器自动管理的,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生内存泄露


栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在windows下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。


碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。


分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloc函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放的,无需我们手工实现。


分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,他的机制是很复杂的。



5、

键值,KVC,键值编码,间接访问对象的属性,通过字符串来指定。这里的字符串就是键,属性值就是值。

键路径,就是用点作为分隔符的键组成的字符串,用于指定一个连接在一起的对象性质序列。通过键路径,可以指定对象中的任意深度的路径,使其指向相关对象的特定属性。


6、

目标是动作消息的接收者,动作时控件发送给目标的消息。

UIBarButtonItem *saveBtn = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(saveRecipe:)];

一个按钮控件的click事件的实现. 在这里, 按钮被按下以后会调用 target(也就是self)上的saveRecipe方法. 按照objC的习惯来说是当click事件发生以后,会给self对象发送一个message导致self对象上的saveRecipe方法的调用.

* Target - Action 主要用来在MVC设计模式中,V和C之间的进行通信。

* V只负责发送对应的action给target,并不关心target具体做了什么。


7、objc内存管理规则

1、对于通过调用带有alloc、copy、mutableCopy、new或者create一词的方法创建的任何对象及其内存,你都拥有所有权。你负责在之后的某个时刻向该对象发送release消息来释放资源。使用类似[[Foo alloc]init...]命令创建的对象需要释放。任何使用类似[foo copy]方法创建的对象需要释放。任何和CreateFoo()类似的调用所返回的对象也需要释放。

2、对于通过不带上述词的方法调用获得的对象,你都没有所有权。这些对象可以再当前执行栈中任意调用,离开当前栈之后,这些对象就不可用了。

说明:从技术上说,对象如果之前没有被保留, 那么在下一个运行循环后会被释放。不过从遵循内存管理规则的角度考虑,你可以假定对象出了作用域后,只要没有被保留,就会被释放。

  通过其他方法调用的对象通常是“自动释放”对象,自动释放对象会在应用程序下次离开运行循环时被释放。

8、autorelease

 作用就是延迟释放,给对象添加延迟释放的标记

自动释放对象 atuorelease,在出了作用域之后,会被自动添加到"最近创建的"自动释放池中,在自动释放池被销毁或者耗尽的时候,会向池中所有对象发送release消息,释放池中对象。


10、单件实例

保证一个类只有一个实例,提供给所有文件共享


11、动态绑定

在运行时确定调用的方法


12、Obj-C优缺点

类别

动态识别

动态绑定

与C/C++混编


缺点:不支持命名空间(用前缀来区分);不支持运算符重载;不支持多重继承;使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(比如内联函数等),性能低劣。


16、delegate是一对一的,并且receiver可以返回值给sender;

notification可以一对多,receiver无法返回值给sender,所以delegate用于sender希望接收到receiver的某个功能反馈,notification用于通知多个对象事件。


17、

KVC key-value-code 键值编码,是通过字符串的形式 间接访问 对象的属性;

KVO key-value-observer 键值监听,监听某个属性的变化。


18、ViewController的loadView,viewDidUnload,viewDidLoad什么时候调用?

loadView: 在Controller的view为nil时调用;

viewDidLoad:在view从nib文件初始化时调用;

viewDidUnload: 内存资源紧张的时候,释放view相关对象,


20、类别的作用

1)利用类别分散实现

将类的实现分散到多个不同文件或多个不同框架中;

2)创建私有方法的前向引用

Cocoa没有任何真正的私有方法,只要知道对象支持的某个方法的名称,即便在该对象的类的接口没有该方法的申明,你也可以调用该方法。不过,如果你这样使用,编译器会报警告,这个时候就可以用类别消除警告。也就是说接口没有该方法申明,则加上类别的该方法申明,就不会有警告;

3)向对象添加非正式协议

创建一个NSObject的类别称为:"创建一个非正式协议",因为NSObject是顶级父类,通过继承关系,所有的类中都有该方法。


类别的局限性:1)无法向类中添加实例变量;2)名称冲突时,类别具有更高的优先级,会取代原来的同名方法。


25、extension可以添加属性,Extension中的方法必须在@implementation中实现,否则编译会报错。


BLOCK


3、block的使用

使用typedef申明一个block

typedef void(^MyBlock)(NSString *);//申明了一个返回值为void,有一个输入参数NSString* ,名为MyBlock的block。

申明block对象

@property(nonatomic, copy) MyBlock myBlock;

注意对象属性一定要用copy,自动复制一份,因为block是存放在栈中,随时会被回收,需要copy操作。

默认,block内部不能修改外部变量,加__block关键字就可以修改外部变量了


3、关键字constant

constant 变量:变量是只读的,初始化后不能被修改;

constant 指针:指针本身不能改变,或是指针指向的内容不能被改变;

constant 函数的形参:表明在函数内部不能改变;

constant 类的成员方法:常函数,不能修改类的成员变量;有时候必须返回constant类型,使得返回值不为"左值"。


4、关键字volatile

总是从原始的地址读取这个变量,而不是从寄存器的备份中得到,这个变量可能被意想不到地改变。

并行设备的硬件寄存器(如:状态寄存器);

中断服务子程序中会访问都的非自动变量;

多线程应用中被几个任务共享的变量;


5、关键字static

static 局部变量;函数内部只初始化一次,下一次调用时会保持上一次的结果;

static 全局变量:能被模块内所有函数访问,不能被其他模块访问;

static 函数:只能被其他函数调用,不能被其他模块调用;

static 成员变量:属于整个类所拥有,对于类的所有对象只有一份拷贝,也就是说被类的所有对象共享;

static 成员方法:属于整个类所拥有,该函数不接收this指针,所以只能访问类的static成员变量。

 


7、线程和进程

进程是系统正在运行的程序,进程之间是相互独立的,一个进程的奔溃不影响其他进程,一个进程至少有一个线程;

线程是进程的一次任务执行,多个线程共享进程分配的内存空间,一个线程奔溃则进程就奔溃。


8、堆和栈的区别

管理方式:栈是由编译器自动管理,无需手动控制;

    堆是由程序员手动管理,容易产生内存泄露。

申请大小:栈是向低地址扩展的数据结构,是一块连续的内存区域,能从栈获得的空间较小;

    堆是向高地址扩展的数据结构,是个不连续的内存区域,能从堆获得的空间较大。

碎片问题:堆,频繁的new/delete会造成内存空间的不连续,出现大量的碎片,使程序效率降低;

    栈,不会存在这个问题,因为栈是先进后出的队列,不可能有一块内存从栈中间弹出。

分配方式:堆,动态分配

    栈,静态分配和动态分配:静态分配,如局部变量的分配,是由编译器完成的,动态分配是由   alloc函数分配,栈的动态分配是由编译器管理的,无需程序员手工实现。

分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持,效率较高;

    堆是C/C++函数库提供的,机制复杂,效率较低。


9、内存管理

有一个原则:谁创建谁释放

1)你使用alloc new copy方法创建对象,若是不用需负责release/autorelease;

2)你用其他方法得到一个对象,则不需要执行任何操作来确保该对象被清理;

3)你保留了一个对象,需要释放该对象,必须保持retain和release方法的使用次数相等。


10、循环引用

对象a创建并引用到了对象b;

对象b创建并引用到了对象c;

对象c创建并引用到了对象b;

这时b的引用计数是2,c的引用计数是1,当a不再使用b,调用release释放对b的所有权,c还引用了b,所以b的引用计数为1,b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。b和c永远保留在内存中。

delegate使用assign(或是weak)就是为了打断循环引用。如果一个UITableViewController拥有一个UITableView,而这个UITableView的delegate对象又是该控制器,若是用retain就会陷入循环引用,没有机会释放这两个对象。


11、

copy在setter方法中先release旧指,再copy新值,有一份新的拷贝,比如block,因为block是保存在栈中,随时可能被回收,所以需要copy

assign 在setter方法中,只是进行赋值,用在基础数据类型int  NSInteger;

retain 在setter方法中先release旧指,再retain新值


12、runLoop

UI事件,"接受消息->等待->处理" 的循环


14、tableView的重用机制

重用机制 简单的说 意思 一行一行 的cell 都是在复用的, 滑动 tableview 的时候,刚离开视图的 cell 会被放到复用池 中,等下一个 cell需要 显示时,会先看复用池中有没有 cell 如果有的时候 ,就从复用池中拿出来cell ,没有的话就重新创建cell 。


visibleCells数组,reusableTableCells数组

tableView总是先从缓存池中找带重用标示符的

比如,有100条数据,屏幕上最多显示10条

1>先用[UITableView alloc]initWithStyle reuseIdentifier:CellIdentifier];

创建10次cell,并给cell执行重用标示符CellIdentifier,那么这10个cell加入到visibleCells数组里,reusableTableCells数组里为空;

2>拖动tableView,但cell1完全移除屏幕时,cell11完全显示(它也是alloc出来的),cell11加入到visibleCells数组里,cell1加入到reusableTableCells数组里;

3>因为reusableTableCells中已经有值了,所以当需要显示新的cell,[ tableView dequeueReusableCellWithIdentifier: CellIdentifier],返回cell1,cell1加入到visibleCells数组,cell1移出reusableTableCells;cell2移出visibleCells数组,cell2加入到reusableTableCells数组。之后再需要显示的cell就可以正常重用了。


18、Model,Controller,View相互通讯的规则:

  1. Controller可以直接和Model通信
  2. Controller也可以直接和View通信
  3. Model和View永远不能直接通信
  4. iOS中View和Controller的通信是透明和固定的,主要通过outlet和action实现
  5. View使用Delegate接口和Controller同步信息
  6. View不直接和数据通信,使用dataSource接口从Controller处获取数据
  7. View的delegate和dataSource一般就是Controller
  8. Controller负责为View翻译和格式化Model的数据
  9. Model使用Notification & KVO的方式分发数据更新信息,Controller可以有选择的监听自己感兴趣的信息。
  10. View也可以监听广播信息,但一般不是Model发出的信息
  11. 一个完整的App就是很多MVC的集合


iOS开发设计模式;

(一)代理模式:

应用场景:当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。

优势:解耦合

敏捷原则:开放-封闭原则

实例:tableview的 数据源delegate,通过和protocol的配合,完成委托诉求。

列表row个数delegate

自定义的delegate

二)观察者模式

应用场景:一般为model层对,controller和view进行的通知方式,不关心谁去接收,只负责发布信息。

优势:解耦合

敏捷原则:接口隔离原则,开放-封闭原则

实例:Notification通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收。

kvo,键值对改变通知的观察者,平时基本没用过。


(三)MVC模式

应用场景:是一中非常古老的设计模式,通过数据模型,控制器逻辑,视图展示将应用程序进行逻辑划分。

优势:使系统,层次清晰,职责分明,易于维护

敏捷原则:对扩展开放-对修改封闭

实例:model-即数据模型,view-视图展示,controller进行UI展现和数据交互的逻辑控制。


(四)单例模式

应用场景:确保程序运行期某个类,只有一份实例,用于进行资源共享控制。

优势:使用简单,延时求值,易于跨模块

敏捷原则:单一职责原则

实例:[UIApplication sharedApplication]。

注意事项:确保使用者只能通过 getInstance方法才能获得,单例类的唯一实例。

java,C++中使其没有公有构造函数,私有化并覆盖其构造函数。

object c中,重写allocWithZone方法,保证即使用户用 alloc方法直接创建单例类的实例,

返回的也只是此单例类的唯一静态变量。



装箱与拆箱 由于NSArray,NSDirectory等类不能直接存储基本数据类型,所以要想在NSArray\ 

NSDirectory中使用基本数据类型,就得使用装箱与拆箱。 

在Objective-C中,可以使用NSNumber和NSValue来实现对数据类型的包装, NSNumber可以实现对基本数据类型的包装,NSValue可以实现对任意类型数据的包 装。 

将基本类型封装成对象叫装箱,从封装的对象中提取基本类型叫拆箱(取消装箱),其它 语言如Java原生支持装箱与拆箱,Ojbective-C不支持自动装箱与拆箱,如果需要得需要 自己来实现装箱与拆箱。 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值