面试题


1.堆和栈的区别? 

一、堆栈空间分配区别: 

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

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

二、堆栈缓存方式区别:

1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立 即释放; 

2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是 一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。 

三、堆栈数据结构区别:

堆(数据结构):堆可以被看成是一棵树,如:堆排序;

栈(数据结构):一种先进后出的数据结构。


2.static 关键字的作用

 (1)设置变量的存储域,函数体内static变量的作用范围为该函数体,不同于auto变 

量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

(2)限制变量的作用域,在模块内的static全局变量可以被模块内所用函数访问,但 不能被模块外其它函数访问; 

(3)限制函数的作用域,在模块内的static函数只可被这一模块内的其它函数调用, 这个函数的使用范围被限制在声明它的模块内; 

(4)在类中的static成员变量意味着它为该类的所有实例所共享,也就是说当某个类 的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见; 

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

3.Object-C 属性特性 (assign,retain,copy,readonly,readwrite,atonmic,nonatomic); 

答: assign , setter 方法直接赋值,不进行任何 retain 操作,为了解决原类型与环循引 用问题 

retain , setter 方法对参数进行 release 旧值再 retain 新值,所有实现都是这个顺序 

copy ,setter 方法进行 Copy 操作,与 retain 处理流程一样,先旧值 release ,再 copy 出新的对象 

readwrite 是可读可写特性;需要生成getter方法和setter方法时readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变 nonatomic ,非原子性访问,不加同步,多线程并发访问会提高性能。 atomic表示多线程安全,一般使用nonatomic 


4.自动释放池是什么,如何工作

答:内存释放池提供了一个对象容器,每次对象发送autorelease消息时,对象的引用 计数并不真正变化,而是向内存释放池中添加一条记录,记下对象的这种要求。直到 当内存释放池发送drainrelease消息时,即当池被销毁前会通知池中的所有对象,全 部发送release消息才会真正将引用计数减少。简单说内存释放池可以自动管理对象释 放问题,这些语句必须要放在下面语句之间,直到池被释放,一个对象要想纳入内存 释放池对象,必须要发送autorelease。 


5.#import #include的区别 @class? 

答:#import不会引起交叉编译的问题。因为在Objective-C中会存在C/C++Object-C 混编的问题,如果用#include引入头文件,会导致交叉编译。

@class方式只是告诉编译器A.h文件中,B*b只是类的声明,具体这个类有什么信息,这里不需要知道。等实现文件中真正需要的时候,才会真正查看B类的信息


6.线程与进程的区别和联系

线程是指进程内的一个执行单元,也是进程内的可调度实体

与进程的区别: (1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间

而进程有自己独立的地址空间; (2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源 (3)线程是处理器调度的基本单位,但进程不是.
4)
二者均可并发执行

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现 系统对应用的并发性。进程和线程的区别在于:简而言之,一个程序至少有一个进程, 一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提 高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有 一个程序运行的入又、顺序执行序列和程序的出又。但是线程不能够独立执行,必须 依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程 的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多 个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和 线程的重要区别。进程是具有一定独立功能的程序关于某个数据集合上的一次运行活 动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,CPU调 度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥 有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但 是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建 和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

7.请解释一下iOS应用的沙盒机制

答:iOS中的沙盒机制(SandBox)是一种安全体系,它规定了应用程序只能在为该 应用创建的文件夹内读取文件,不可以访问其他地方的内容。所有的非代码文件都保 存在这个地方,比如图片、声音、属性列表和文本文件等。 

1.每个应用程序都在自己的沙盒内 

2.不能随意跨越自己的沙盒去访问别的应用程序沙盒的内容

 3.应用程序向外请求或接收数据都需要经过权限认证 




8.NSString NSMutableString有什么区别

答:NSString是一个不可变的字符串对象。这不是表示这个对象声明的变量的值不可 变,而是表示它初始化以后,你不能改变该变量所分配的内存中的值,但你可以重新 分配该变量所处的内存空间。而NSMutableString是可变的,意味着你可以追加它的内 存空间,或者修改它所分配的内存空间中的值。 

9.UIViewController的生命周期方法调用顺序 

答:当一个视图控制器被创建,并在屏幕上显示的时候。 代码的执行顺序 

1 alloc 创建对象,分配空间 

2init (initWithNibName) 初始化对象,初始化数据 

3loadView   从nib载入视图 ,通常这一步不需要去干涉。除非你没有使用xib文件创建视图 

4viewDidLoad  载入完成,可以进行自定义数据以及动态创建其他控件 

 5viewWillAppear  视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了

6viewDidAppear  视图已在屏幕上渲染完成

当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反 

1viewWillDisappear 视图将被从屏幕上移除之前执行

2viewDidDisappear 视图已经被从屏幕上移除,用户看不到这个视图了 

3dealloc 视图被销毁,此处需要对你在initviewDidLoad中创建 的对象进行释放 


10.介绍一下你对面向对象概念的理解

答:包括三个特征:继承、封装、多态。 

类的继承性是指从已有的一个类来extends子类,子类具有了父类的所有特征,同时, 子类也可以有新的特性。比如:人是一个类,男人具有了人类的所有的特性,比如思 考,比如劳动。同时,男人也有新的特性,比如男人会长胡子。 

类的封装是指类把所有的操作都封闭起来,仅仅提供接又出来让其他人使用,使用的

人没有必要懂得类里面的操作,只需要懂得操作接又就可以了。比如开汽车,我们只

需要懂得方向盘、刹车、油门等等的使用就可以了,没有必要知道刹车是如何构成的

封闭好的操作。同时,封装也提高了程序的可替换性。比如两个汽车公司实现刹车的

方式不一样,但是,只要我们学会了使用刹车,那么,开两个汽车公司的车就都没有

问题了,我们不需要考虑他们怎样实现刹车这门技术的。

类的多态性是一个对象的某项功能可以处理不同类型的问题,或者一个子类可以将父 类的某个功能替换成新的功能,具体到编程的方面来说实现类的多态有overrideoverload,也就是覆写和重载。 

同时面向对象还有一个很重要的概念:抽象。抽象就是一个事物的本质。当然对于本

质,不同的角度却会有不同的理解。男人,在和女人一起的时候,它的本质是人。在

和所有的生物一起的时候,它的本质是动物。



11.什么是MVC? 

答:系统分为三个部分:Model,View,Controller。在cocoa中,你的程序中的每一 个object(对象)都将明显地仅属于这三部分中的一个,而完全不属于另外两个。 MVC可以帮助确保帮助实现程序最大程度的可重用性。各MVC元素彼此独立运作, 通过分开这些元素,可以构建可维护,可独立更新的程序组建。 

delegate设计模式; target-action设计模式

 

12.响应链(Responder chain)是什么?它是如何发挥作用的

:当事件发生的时候,响应链首先被发送给第一个响应者(往往是事件发生的视图, 也就是用户触摸屏幕的地方)。事件将沿着响应者链一直向下传递,直到被接受并作 出处理。一般来说,第一响应这是个视图对象或者其子类,当其被触摸后事件就交由 它处理,如果他不处理,时间就会被传递给视图控制器对象UIViewController(如果 存在),然后是它的父视图对象(superview),以此类推直到顶层视图。接下来会沿 着顶层视图(top view)到窗又(UIwindow 对象) 再到程序的(UIApplication对象), 如果整个过程都没有响应这个事件,则该事件被丢弃,一般情况下,在响应链中只要 有对象处理事件,事件就会被传递 

典型的响应路线图如:

First Responser --> The Window -->The Applicationn --> App Delegate 



14、ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?默认的操作是什么? 

当程序接到内存警告时ViewController将会收到这个消息:didReceiveMemoryWarning 从iOS3.0开始,不需要重载这个函数,把释放内存的代码放到viewDidUnload中去。 这个函数的默认实现是:检查controller是否可以安全地释放它的view,如果view可以被释放,那么这个函数释放view并 

调用viewDidUnload。重载这个函数来释放controller中使用的其他内存。但要记得调用这个函数的super实现来允许父 类(一般是UIVIewController)释放view。 如果你的ViewController保存着view的子view的引用,那么,在早期的iOS版本中,你应该在这个函数中来释放这些引 用。而在iOS3.0或更高版本中,你应该在viewDidUnload中释放这些引用 



14、为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的? 

会引起循环引用----若是retain,在alloc一次之后,若release一次,会导致内训泄漏,若release两次会导致两个 对象的dealloc嵌套执行,结果就是都没有执行成功,最后崩溃! 所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系: 

  • 对象a创建并引用到了对象b.   
  • 对象b创建并引用到了对象c. 
  • 对象c创建并引用到了对象b. 

这时候b和c的引用计数分别是2和1。 当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,b不会被释放。 b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。 这种情况,必须打断循环引用,通过其他规则来维护引用关系。我们常见的delegate往往是assign方式的属性而不是 retain方式 的属性,赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。 如果一个UITableViewController 对象a通过retain获取了UITableView对象b的所有权,这个UITableView对象b的 delegate又是a,如果这个delegate是retain方式的,那基本上就没有机会释放这两个对象了。自己在设计使用 delegate模式时,也要注意这点。 

15、简述NotificationCenter、KVC、KVO、Delegate?并说明它们之间的区别?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值