iOS 面试宝典 没有比这更全的了
(持续更新) - 简书1.ios 高性能编程 (1). 内层 最小的内层平均值和峰值 (2). 耗电量 高效的算法和数据结构 (3). 初始化时间 app 再启动时花费的时间 例如:app 启动时可能包含操作...
1.ios 高性能编程
(1). 内层 最小的内层平均值和峰值
(2). 耗电量 高效的算法和数据结构
(3). 初始化时间 app 再启动时花费的时间 例如:app 启动时可能包含操作:
1>. 检查版本更新
2>. 初始化三方地图环信 (可能还有登录) 分享统计
3>. 游客身份可登录下需要获取用户的信息
4>. 其他业务接口
后果就是首页界面感觉很卡,明明都是在子线程发送的数据请求。为什么会这样样呢。1. 即使是 cpu 的多核在能够并发,但是 cpu 在同一个时间段内只能执行一个任务。线程太多 cpu 需要在线程间切换,也是耗性能的 2. 这是应为那么多接口请求的数据可能都需要需要刷新首页的界面相关视图。好几次连续的刷新,也会使界面很卡,必须要求服务端端接口优化 (如:服务端接口转发)。
(4). 执行速度耗时的操作放在子线程
(5). 响应速度耗时的算法和业务逻辑尽量转到后台
(6). 本地存储使用正确的存储方式
(7). 互操作性
(8). 网络环境在网络状态不好时,给出合理的提示
(9). 数据刷新:数据刷新时优美的动画
(10). 多用户支持,是单点登录还是多用户登录
(11). 安全使用高效的加密方式
(12). 崩溃:尽量使用自动崩溃解析品台
(13). 应用性能分析采样埋点
参考: 高性能编程
2. 数据结构
答案:数据结构
3.Swift 和 OC 的区别
苹果宣称 Swift 的特点是:
(1) 快速、现代、安全、互动,而且明显优于 Objective-C 语言
(2) 可以使用现有的 Cocoa 和 Cocoa Touch 框架
(3)Swift 取消了 Objective C 的指针 / 地址等不安全访问的使用
(4) 提供了类似 Java 的名字空间 (namespace)、泛型 (generic)var、运算对象重载(operator overloading
(5)Swift 被简单的形容为 “没有 C 的 Objective-C”(Objective-C without the C)
(6) 为苹果开发工具带来了 Xcode Playgrounds 功能,该功能提供强大的互动效果,能让 Swift 源代码在撰写过程中实时显示出其运行结果;
(7) 基于 C 和 Objective-C,而却没有 C 的一些兼容约束;
(8) 采用了安全的编程模式;
(9) 界面基于 Cocoa 和 Cocoa Touch 框架;
(10) 舍弃 Objective C 早期应用 Smalltalk 的语法,保留了 Smalltalk 的动态特性,全面改为句点表示法
(11) 类型严谨 对比 oc 的动态绑定
3.synthesize&denamic
(1) 通过 @synthesize 指令告诉编译器在编译期间产生 getter/setter 方法。
(2) 通过 @dynamic 指令,自己实现方法。
有些存取是在运行时动态创建的,如在 CoreData 的 NSManagedObject 类使用的某些。如果你想这些情况下,声明和使用属性,但要避免缺少方法在编译时的警告,你可以使用 @dynamic 动态指令,而不是 @synthesize 合成指令。
4. 在项目开发中常用 的开发工具有哪些?
Instrument /beyondCompare /git Cornerstone /ApplicationLoader idea(编写 h5 和 RN)
*UITableView&UICollection
UICollectionView 是 iOS6 新引进的 API,用于展示集合视图,布局更加灵活,其用法类似 于 UITableView。而 UICollectionView、UICollectionViewCell 与 UITableView、UITableViewCell 在用法上有相似的也有不同的,下面是一些基本的使用方法:对于 UITableView,仅需要 UITableViewDataSource,UITableViewDelegate 这两个协议,使用 UICollectionView 需要实现 UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout 这三个协议,这是因为 UICollectionViewDelegateFlowLayout 实际上是 UICollectionViewDelegate 的一个子协议,它继承 了 UICollectionViewDelegate,它的作用是提供一些定义 UICollectionView 布局模式的函数
5.NSProxy&NSObject
NSObjetct:
NSObject 协议组对所有的 Object-C 下的 objects 都生效。 如果 objects 遵从该协议,就会被看作是 first-class objects(一级类)。 另外,遵从该协议的 objects 的 retain,release,autorelease 等方法也服从 objects 的管理和在 Foundation 中定义的释放方法。一些容器中的对象也可以管理这些 objects,比如说 NSArray 和 NSDictionary 定义的对象。 Cocoa 的根类也遵循该协议,所以所有继承 NSObjects 的 objects 都有遵循该协议的特性。
NSProXY:
NSProxy 是一个虚基类,它为一些表现的像是其它对象替身或者并不存在的对象定义一套 API。一般的,发送给代理的消息被转发给一个真实的对象或者代理本身 load(或者将本身转换成) 一个真实的对象。NSProxy 的基类可以被用来透明的转发消息或者耗费巨大的对象的 lazy 初始化。
7. 传值通知 & 推送通知(本地 & 远程)
传值通知: 传值的一种方式
推送通知: 推送到用户手机对应的 App 上(主要是不在前台的情况), 用户获得资源的一种手段。普通情况下,都是客户端主动的 pull。推送则是服务器端主动 push。
本地通知: local notification,用于基于时间行为的通知,比如有关日历或者 todo 列表的小应用。另外,应用 如果在后台执行,iOS 允许它在受限的时间内运行,它也会发现本地通知有用。比如,一个应用,在后台运行,向应用的服务器端获取消息,当消息到达时,比如下载更新版本的提示消息,通过本地通知机制通知用户。
本地通知是 UILocalNotification 的实例,主要有三类属性:
scheduled time,时间周期,用来指定 iOS 系统发送通知的日期和时间;
notification type,通知类型,包括警告信息、动作按钮的标题、应用图标上的 badge(数字标记)和播放的声音;
自定义数据,本地通知可以包含一个 dictionary 类型的本地数据。
对本地通知的数量限制,iOS 最多允许最近本地通知数量是 64 个,超过限制的本地通知将被 iOS 忽略。
远程通知(需要服务器)。流程大概是这样的
1> 生成 CertificateSigningRequest.certSigningRequest 文件
2> 将 CertificateSigningRequest.certSigningRequest 上传进 developer,导出. cer 文件
3> 利用 CSR 导出 P12 文件
4> 需要准备下设备 token 值(无空格)
5> 使用 OpenSSL 合成服务器所使用的推送证书一般使用极光 / 友盟推送,步骤是一样的,只是我们使用的服务器是极光的,不需要自己大服务器!
8. 第三方库 & 第三方平台
第三方库: 一般是指大牛封装好的一个框架(库),或者第三方给我们提供的一个库,这里比较笼统
* 第三方平台:指第三方提供的一些服务,其实很多方面跟第三方库是一样的,但是还是存在一些区别。
库:AFN,ASI,Alomofire,MJRefresh,MJExtension,MBProgressHUD
平台:极光,百度,友盟,Mob,环信
9.imageName 和 ImageWithContextOfFile 的区别?哪个性能高
用 imageNamed 的方式加载时,图片使用完毕后缓存到内存中,内存消耗多,加载速度快。即使生成的对象被 autoReleasePool 释放了,这份缓存也不释放,如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存。
imageNamed 采用了缓存机制,如果缓存中已加载了图片,直接从缓存读就行了,每次就不用再去读文件了,效率会更高。
ImageWithContextOfFile 加载,图片是不会缓存的,加载速度慢。
大量使用 imageNamed 方式会在不需要缓存的地方额外增加开销 CPU 的时间. 当应用程序需要加载一张比较大的图片并且使用一次性,那么其实是没有必要去缓存这个图片的,用 imageWithContentsOfFile 是最为经济的方式, 这样不会因为 UIImage 元素较多情况下,CPU 会被逐个分散在不必要缓存上浪费过多时间.
10.NSCache&NSDictionary
NSCache 与可变集合有几点不同:
NSCache 类结合了各种自动删除策略,以确保不会占用过多的系统内存。如果其它应用需要内存时,系统自动执行这些策略。当调用这些策略时,会从缓存中删除一些对象,以最大限度减少内存的占用。
NSCache 是线程安全的,我们可以在不同的线程中添加、删除和查询缓存中的对象,而不需要锁定缓存区域。
不像 NSMutableDictionary 对象,一个缓存对象不会拷贝 key 对象。NSCache 和 NSDictionary 类似,不同的是系统回收内存的时候它会自动删掉它的内容。
(1) 可以存储 (当然是使用内存)
(2) 保持强应用, 无视垃圾回收. => 这一点同 NSMutableDictionary
(3) 有固定客户. 位运算 NSCache 特点: a> 线程安全的 b> 当内存不足的时候, 自动释放 c> 缓存数量和缓存成本区别 NSMutableDictionary1> 不能也不应该遍历 2> NSCache 对 key 强引用, NSMutableDictionary 对 key 进行 copy
11.UIView 的 setNeedsDisplay 和 setNeedsLayout 方法
(1) 在 Mac OS 中 NSWindow 的父类是 NSResponder,而在 iOS 中 UIWindow 的父类是 UIVIew。程序一般只有一个窗口但是会又很多视图。
(2)UIView 的作用:描画和动画,视图负责对其所属的矩形区域描画、布局和子视图管理、事件处理、可以接收触摸事件、事件信息的载体、等等。
(3)UIViewController 负责创建其管理的视图及在低内存的时候将他们从内存中移除。还为标准的系统行为进行响应。
(4)layOutSubViews 可以在自己定制的视图中重载这个方法,用来调整子视图的尺寸和位置。
(5)UIView 的 setNeedsDisplay(需要重新显示, 绘制) 和 setNeedsLayout(需要重新布局) 方法。首先两个方法都是异步执行的。而 setNeedsDisplay 会自动调用 drawRect 方法,这样可以拿到 UIGraphicsGetCurrentContext,就可以画画了。而 setNeedsLayout 会默认调用 layoutSubViews,就可以处理子视图中的一些数据。
综上所述:setNeedsDisplay 方便绘图,而 layoutSubViews 方便出来数据。setNeedDisplay 告知视图它发生了改变,需要重新绘制自身,就相当于刷新界面.
12、UILayer&UIView
UIView 是 iOS 系统中界面元素的基础,所有的界面元素都继承自它。它本身完全是由 CoreAnimation 来实现的(Mac 下似乎不是这 样)。它真正的绘图部分,是由一个叫 CALaye(Core Animation Layer)的类来管理。UIView 本身,更像是一个 CALayer 的管理器,访问它的绘图 / 坐标有关的属性,例如 frame,bounds 等等,实际上内部都是在访问它所包含的 CALayer 的相关属性。
UIView 有个重要属性 layer,可以返回它的主 CALayer 实例。
UIView 的 CALayer 类似 UIView 的子 View 树形结构,也可以向它的 layer 上添加子 layer,来完成某些特殊的表示。即 CALayer 层是可以嵌套的。
UIView 的 layer 树形在系统内部,被维护着三份 copy。分别是逻辑树,这里是代码可以操纵的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树,其内容就是当前正被显示在屏幕上得内容。
动画的运作:对 UIView 的 subLayer(非主 Layer)属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是 0.5 秒。
坐标系统:CALayer 的坐标系统比 UIView 多了一个 anchorPoint 属性,使用 CGPoint 结构表示,值域是 0~1,是个比例值。
渲染:当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用 setNeedsDisplay 方法来重绘显示。
变换:要在一个层中添加一个 3D 或仿射变换,可以分别设置层的 transform 或 affineTransform 属性。
变形:Quartz Core 的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。CATransform3D 的一套方法提供了一些魔术般的变换效果。
13、layoutSubViews&drawRects
layoutSubviews 在以下情况下会被调用 (视图位置变化是触发):
1、init 初始化不会触发 layoutSubviews.
2、addSubview 会触发 layoutSubviews。
3、设置 view 的 Frame 会触发 layoutSubviews,当然前提是 frame 的值设置前后发生了变化。
4、滚动一个 UIScrollView 会触发 layoutSubviews。
5、旋转 Screen 会触发父 UIView 上的 layoutSubviews 事件。
6、改变一个 UIView 大小的时候也会触发父 UIView 上的 layoutSubviews 事件。
7、直接调用 setLayoutSubviews。drawRect 在以下情况下会被调用:
1、如果在 UIView 初始化时没有设置 rect 大小,将直接导致 drawRect 不被自动调用。drawRect 是在 Controller->loadView, Controller->viewDidLoad 两方法之后掉用的. 所以不用担心在 控制器中, 这些 View 的 drawRect 就开始画了. 这样可以在控制器中设置一些值给 View(如果这些 View draw 的时候需要用到某些变量 值).
2、该方法在调用 sizeToFit 后被调用,所以可以先调用 sizeToFit 计算出 size。然后系统自动调用 drawRect: 方法。
3、通过设置 contentMode 属性值为 UIViewContentModeRedraw。那么将在每次设置或更改 frame 的时候自动调用 drawRect:。
4、直接调用 setNeedsDisplay,或者 setNeedsDisplayInRect: 触发 drawRect:,但是有个前提条件是 rect 不能为 0。drawRect 方法使用注意点:
1、若使用 UIView 绘图,只能在 drawRect:方法中获取相应的 contextRef 并绘图。如果在其他方法中获取将获取到一个 invalidate 的 ref 并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用 setNeedsDisplay 或者 setNeedsDisplayInRect,让系统自动调该方法。
2、若使用 calayer 绘图,只能在 drawInContext: 中(类似 drawRect)绘制,或者在 delegate 中的相应方法绘制。同样也是调用 setNeedDisplay 等间接调用以上方法 3、若要实时画图,不能使用 gestureRecognizer,只能使用 touchbegan 等方法来调用 setNeedsDisplay 实时刷新屏幕
14、UDID&UUID
UDID 是 Unique Device Identifier 的缩写, 中文意思是设备唯一标识.
在很多需要限制一台设备一个账号的应用中经常会用到, 在 Symbian 时代, 我们是使用 IMEI 作为设备的唯一标识的, 可惜的是 Apple 官方不允许开发者获得设备的 IMEI.
[UIDevice currentDevice] uniqueIdentifier]
但是我们需要注意的一点是, 对于已越狱了的设备, UDID 并不是唯一的. 使用 Cydia 插件 UDIDFaker, 可以为每一个应用分配不同的 UDID. 所以 UDID 作为标识唯一设备的用途已经不大了.
UUID 是 Universally Unique Identifier 的缩写, 中文意思是通用唯一识别码.
由网上资料显示, UUID 是一个软件建构的标准, 也是被开源软件基金会 (Open Software Foundation,OSF) 的组织在分布式计算环境 (Distributed Computing Environment,DCE) 领域的一部份. UUID 的目的, 是让分布式系统中的所有元素, 都能有唯一的辨识资讯, 而不需要透过中央控制端来做辨识资 讯的指定.
备注:UDID 并不是一定不会变,如:重新开关机、手机越狱都会变。决绝办法是将 UDID 保存在钥匙串中,用时去钥匙串中取。UUID 倒是永远不变的,使用 xcode 自带工具 / 蒲公英工具获取,但不能直接通过代码获取。
15、CPU&GPU
CPU: 中央处理器(英文 Central Processing Unit)是一台计算机的运算核心和控制核心。CPU、内部存储器和输入 / 输出设备是电子计算机三大核心部件。其功能主要是解释计算机指令以及处理计算机软件中的数据。
GPU: 英文全称 Graphic Processing Unit,中文翻译为 “图形处理器”。一个专门的图形核心处理器。GPU 是显示卡的“大脑”,决定了该显卡的档次和大部分性能,同时也是 2D 显示卡和 3D 显示卡的区别依据。2D 显示芯片在处理 3D 图像和特效时主要依赖 CPU 的处理能力,称为“软加速”。3D 显示芯片是将三维图像和特效处理功能集中在显示芯 片内,也即所谓的“硬件加速” 功能。
16、点(pt)& 像素(px)
像素(pixels)是数码显示上最小的计算单位。在同一个屏幕尺寸,更高的 PPI(每英寸的像素数目),就能显示更多的像素,同时渲染的内容也会更清晰。
点(points)是一个与分辨率无关的计算单位。根据屏幕的像素密度,一个点可以包含多个像素(例如,在标准 Retina 显示屏上 1 pt 里有 2 x 2 个像素)。当你为多种显示设备设计时,你应该以 “点” 为单位作参考,但设计还是以像素为单位设计的。这意味着仍然需要以 3 种不同的分辨率导出你的素材,不管你以哪种分辨率设计你的应用。
17、属性与成员变量:
成员变量是不与外界接触的变量,应用于类的内部,如果你说那用 @Public 外部不就是可以访问了么。简单的说 public 只能适当使用,不要泛滥,否则就像你把钥匙插在你自己家门上了。谁来都可以开门。毫无安全性。
由于成员变量的私有性,为了解决外部访问的问题就有了属性变量。属性变量个人认为最大的好处就是让其他对象访问这个变量。而且你可以设置只读、可写等等属性,同时设置的方法我们也可以自己定义。记住一点,属性变量主要是用于与其他对象相互交互的变量如果对于上面所说还是含糊不清那就记住这几点吧!
1. 只有类内使用,属性为 private,那么就定义成员变量。
2. 如果你发现你需要的这个属性需要是 public 的,那么毫不犹豫就用属性在. h 中定义。
3. 当你自己内部需要 setter/getter 实现一些功能的时候,用属性在. m 中定义。
18、全局变量和静态变量的区别
1> 修饰符全局变量在声明源文件之外使用, 需要 extern 引用一下; 静态变量使用 static 来修饰
2> 存储地址 两者都是存储在静态存储区, 非堆栈上, 它们与局部变量的存储分开
3> 生命周期两者都是在程序编译或加载时由系统自动分配的, 程序结束时消亡
4> 外部可访问性 全局变量在整个程序的任何地方均可访问, 而静态变量相当于面向对象中的私有变量, 他的可访问性只限定于声明它的那个源文件, 即作用于仅局限于本文件中
19、static 关键字的作用
1. 函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
2. 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
3. 在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
4. 在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
5. 在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的 static 成员变量。
20、分类 拓展 协议中哪些可以声明属性?
1. 继承:
1> 继承可以增加 / 修改 / 删除方法,并且可以增加属性。
2> 当添加的方法和父类方法相同时, 父类方法仍可使用.
2. 类别:
1> 针对系统提供的有些类, 系统本身不提倡继承, 因为这些类的内部实现对继承有所限制
2> 类别可以将自己构建的类中的方法进行分组, 对于大型的类, 提高了可维护性
3. 分类的作用
1> 将类的实现分散到多个不同文件或多个不同框架中。
2> 创建对私有方法的前向引用。
3> 向对象添加非正式协议。 (非正式协议: 即 NSObject 的分类, 声明方法可以不实现, OC2.0 以前 protocal 没有 @optional, 主要使用分类添加可选协议方法
oc 中声明方法不实现, 不调用则只警告不报错
正式协议的优点: 可继承, 泛型约束
如 kvo 的 observeValueForKeyPath 属于 NSObject 的分类, 且不需要调父类, 说明可选实现该方法, 没警告可能是编译器规则过滤)
4、category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
5、分类的局限性
无法向类中添加新的实例变量,类别没有位置容纳实例变量。
无法添加实例变量的局限可以使用字典对象解决 (将需要存储的内容存字典中)
21、 继承和类别的区别
1、继承:
继承可以增加 / 修改 / 删除方法,并且可以增加属性。当添加的方法和父类方法相同时, 父类方法仍可使用.
2、类别:
1> 针对系统提供的有些类, 系统本身不提倡继承, 因为这些类的内部实现对继承有所限制
2> 类别可以将自己构建的类中的方法进行分组, 对于大型的类, 提高了可维护性
3、分类的作用
1> 将类的实现分散到多个不同文件或多个不同框架中。
2> 创建对私有方法的前向引用。
3> 向对象添加非正式协议。 (非正式协议: 即 NSObject 的分类, 声明方法可以不实现, OC2.0 以前 protocal 没有 @optional, 主要使用分类添加可选协议方法 oc 中声明方法不实现, 不调用则只警告不报错 正式协议的优点: 可继承, 泛型约束如 kvo 的 observeValueForKeyPath 属于 NSObject 的分类, 且不需要调父类, 说明可选实现该方法, 没警告可能是编译器规则过滤)
4> category 可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
4、分类的局限性 无法向类中添加新的实例变量,类别没有位置容纳实例变量。 无法添加实例变量的局限可以使用字典对象解决 (将需要存储的内容存字典中)
22、category&extension
类别主要有三个作用
(1) 可以将类的实现分散到多个不同文件或多个不同框架中,方便代码管理。也可以对框架提供类的扩展(没有源码,不能修改)。
(2) 创建对私有方法的前向引用:如果其他类中的方法未实现,在你访问其他类的私有方法时编译器报错这时使用类别,在类别中声明这些方法(不必提供方法实现),编译器就不会再产生警告
(3) 向对象添加非正式协议:创建一个 NSObject 的类别称为 “创建一个非正式协议”,因为可以作为任何类的委托对象使用。
他们的主要区别是:
1、形式上来看,extension 是匿名的 category。
2、extension 里声明的方法需要在 main implementation 中实现,category 不强制要求。
3、extension 可以添加属性(变量),category 不可以。 Category 和 Extension 都是用来给已定义的类增加新的内容的。
4、Category 和原有类的耦合更低一些,声明和实现都可以写在单独的文件里。但是只能为已定义类增加 Method,而不能加入实例变量。
5、extensions 可以认为是一个私有的 Category。
Extension 耦合比较高,声明可以单独写,但是实现必须写在原有类的 @implementation 中。可以增加 Method 和实例变量。
Extension 给人感觉更像是在编写类时为了封装之类的特性而设计,和类是同时编写的。而 category 则是在用到某一个 framework 中的类时临时增加的特性。
Extension 的一个特性就是可以重新声明一个实例变量,将之从 readonly 改为对内 readwrite.
使用 Extension 可以更好的封装类,在 h 文件中能看到的都是对外的接口,其余的实例变量和对内的 @property 等都可以写在 Extension,这样类的结构更加清晰。
23.NSArray 和 NSDictionary
1> iOS 遍历数组 / 字典的方法
数组:
1.for 循环 forin
2.enumerateObjectsUsingBlock(正序)
3.enumerateObjects With Options: usingBlock:(多一个遍历选项, 不保证顺序)
字典:
1. for(NSString *object in [testDic allValues])
2. for(id akey in [testDic allKeys]) {
[sum appendString:[testDic objectForKey:akey]];
}
3. [testDic enumerateKeysAndObjectsUsingBlock:^(idkey,idobj,BOOL*stop) {
[sum appendString:obj];
} ];
2> 速度:
数组, 增强 for 最快, 普通 for 和 block 速度差不多, 增强最快是因为增强 for 语法会对容器里的元素的内存地址建立缓冲, 遍历的时候直接从缓冲中取元素地址而不是通过调用方法来获取, 所以效率高. 这也是使用增强 for 时不能在循环体中修改容器元素的原因之一 (可以在循环体中添加标记, 在循环体外修改元素)
对于字典, allValues 最快, allKey 和 block 差不多, 原因是 allKey 需要做 objcetForKey 的方法
24. 如何避免循环引用
哪些地方可能导致循环引用:
1. block 的循环引用
2. a->b->c->a
3. 代理 (应该使用 assign) 使用了 retain 或者 strong
4. 两个对象相互强引用,都无法 release,解决办法为一个使用 strong,一个使用 assign(weak)
25.CFSocket 使用有哪几个步骤。
答:创建 Socket 的上下文;创建 Socket ;配置要访问的服务器信息;封装服务器信息;连接服务器;
26.oc 几种操作 Socket 的方法?
答:CFNetwork 、CFSocket 和 BSD Socket 。AsyncSocket
27. 解析 XML 文件有哪几种方式?
答:以 DOM 方式解析 XML 文件;以 SAX 方式解析 XML 文件;
28. 什么是沙盒模型?哪些操作是属于私有 api 范畴?
答:某个 iphone 工程进行文件操作有此工程对应的指定的位置,不能逾越。
iphone 沙箱模型的有四个文件夹 documents,tmp,app,Library,永久数据存储一般放 documents 文件夹,得到模拟器的路径的可使用 NSHomeDirectory() 方法。Nsuserdefaults 保存的文件在 tmp 文件夹里。
29. 在一个对象的方法里面:self.name= “object”;和 name =”object” 有什么不同吗?
答:self.name =”object”:会调用对象的 setName() 方法,
name = “object”:会直接把 object 赋值给当前对象的 name 属性。
30. 创建控制器、视图的方式
创建控制器的方式
(1) 通过代码的方式加载 UIViewController *controller = [[UIViewController alloc] init]; (2) 通过 stroyboard 来加载 加载 storyboard 中箭头指向的 viewController UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
// 加载箭头指向的 viewController
CZViewController *controller = [storyboard instantiateInitialViewController];
加载 storyboard 中特定标示的 viewController(storyboard 可以有多个 controller) CZViewController *controller = [storyboard instantiateViewControllerWith Identifier:@"two"];
(3) 传统方法
1. 创建 Xib, 并指定 xib 的 files owner 为自定义控制器类 (为了能连线关联管理 IB 的内容)
2. xib 中要有内容,且 xib 中描述的控制器类的 view 属性要与 xib 的 view 控件完成关联(关联 方法两种, 一种是 control+files owner 拖线到 xib 中搭建的指定 view 控件, 另一种是指定 xib 中的 view 拖线到 @interface)
3. 从 xib 加载 viewController CZViewController *controller = [[CZViewController alloc]initWithNibName: @ “CZOneView” bundle:nil];4.bundle 中取出 xib 内容 CZViewController *vc = [[NSBundle mainBundle] loadNibNamed:@"Two" owner:nil options:nil].lastObject;
创建视图的方式
1. 用系统的 loadView 方法创建控制器的视图
2. 如果指定加载某个 storyboard 文件做控制器的视图,就会加载 storyboard 里面的描述去创 建 view
3. 如果指定读取某个 xib 文件做控制器的视图,就根据指定的 xib 文件去加载创建
4. 如果有 xib 文件名和控制器的类名前缀(也就是去掉 controller)的名字一样的 xib 文 件 就会用这个 xib 文件来创建控件器的视图 例:控件器的名为 MJViewController xib 文件名为 MJView.xib 如果 xib 文件名后有一个字不一样就不会去根据它去创建如:MJView8.xib
5. 找和控制器同名的 xib 文件去创建
6. 如果以上都没有就创建一个空的控制器的视图;
31.UIWindow
是一种特殊的 UIView, 通常在一个程序中只会有一个 UIWindow, 但可以手 动创建多个 UIWindow, 同时加到程序里面。UIWindow 在程序中主要起到三个作用:
1、作为容器, 包含 app 所要显示的所有视图
2、传递触摸消息到程序中 view 和其他对象
3、与 UIViewController 协同工作, 方便完成设备方向旋转的支持
32. 简述内存分区情况
1). 代码区:存放函数二进制代码
2). 数据区:系统运行时申请内存并初始化,系统退出时由系统释放。存放全局变量、静态变量、常量
3). 堆区:通过 malloc 等函数或 new 等操作符动态申请得到,需程序员手动申请和释放
4). 栈区:函数模块内申请,函数结束时由系统自动释放。存放局部变量、函数参数
36. 队列和栈有什么区别答:
33. 队列和栈有什么区别
队列和栈是两种不同的数据容器。从” 数据结构” 的角度看,它们都是线性结构,即数据元素之间的关系相同。
队列是一种先进先出的数据结构,它在两端进行操作,一端进行入队列操作,一端进行出列队操作。
栈是一种先进后出的数据结构,它只能在栈顶进行操作,入栈和出栈都在栈顶操作。
34.iOS 的系统架构
答:iOS 的系统架构分为(核心操作系统层 theCore OS layer )、(核心服务层 theCore Services layer )、(媒体层 theMedia layer )和(Cocoa 界面服务层 the Cocoa Touch layer )四个层次。
35. 控件主要响应 3 种事件
答:1). 基于触摸的事件; 2). 基于值的事件; 3). 基于编辑的事件。
36.xib 文件的构成分为哪 3 个图标?都具有什么功能。
答:File’s Owner 是所有 nib 文件中的每个图标,它表示从磁盘加载 nib 文件的对象;
First Responder 就是用户当前正在与之交互的对象;View 显示用户界面;完成用户交互;是 UIView 类或其子类。
37. 简述视图控件器的生命周期。
答:loadView 在 controller 的 view 为 nil 时调用。尽管不直接调用该方法,如多手动创建自己的视图,那么应该覆盖这个方法并将它们赋值给试图控制器的 view 属性。
viewDidLoad 只有在视图控制器将其视图载入到内存之后才调用该方法,这是执行任何其他初始化操作的入口。
viewVillAppear 当试图将要添加到窗口中并且还不可见的时候或者上层视图移出图层后本视图变成顶级视图时调用该方法,用于执行诸如改变视图方向等的操作。实现该方法时确保调用 [super viewWillAppear:
viewDidAppear 当视图添加到窗口中以后或者上层视图移出图层后本视图变成顶级视图时调用,用于放置那些需要在视图显示后执行的代码。确保调用 [super viewDidAppear:]。
viewWillDisappear-UIViewController 对象的视图即将消失、被覆盖或是隐藏时调用
viewWillDisappear-UIViewController 对象的视图即将消失、被覆盖或是隐藏时调用;
viewDidDisappear-UIViewController 对象的视图已经消失、被覆盖或是隐藏时调用;
viewVillUnload-当内存过低时,需要释放一些不需要使用的视图时,即将释放时调用;
viewDidUnload 当试图控制器从内存释放自己的方法的时候调用,当内存过低,释放一些不需要的视图。在这里实现将 retain 的 view release,如果是 retain 的 IBOutlet view 属性则不要在这里 release,IBOutlet 会负责 release 。
38. 应用的生命周期 各个程序运行状态时代理的回调:
-(BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 告诉代理进程启动但还没进入状态保存
-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 告诉代理启动基本完成程序准备开始运行
- (void)applicationWillResignActive:(UIApplication *)application 当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了
- (void)applicationDidBecomeActive:(UIApplication *)application 当应用程序入活动状态执行,这个刚好跟上面那个方法相反
- (void)applicationDidEnterBackground:(UIApplication *)application 当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可
- (void)applicationWillEnterForeground:(UIApplication *)application 当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
- (void)applicationWillTerminate:(UIApplication *)application 当程序将要退出是被调用,通常是用来保存数据和一些退出前的清理工作。
39. 简要说明一下 APP 的启动过程,main 文件说起,main 函数中有什么函数?作用是什么?
打开程序——->执行 main 函数———>UIAPPlicationMain 函数——->初始化 UIAPPlicationMain 函数 (设置代理,开启事件循环)———> 监听系统事件—->程序结束
先执行 main 函数,main 内部会调用 UIApplicationMain 函数
UIApplicationMain 函数作用:
(1)、根据传入的第三个参数创建 UIApplication 对象或它的子类对象。如果该参数为 nil, 直接使用该 UIApplication 来创建。(该参数只能传人 UIApplication 或者是它的子类)
(2)、根据传入的第四个参数创建 AppDelegate 对象, 并将该对象赋值给第 1 步创建的 UIApplication 对象的 delegate 属性。
(3)、开启一个事件循环, 循环监控应用程序发生的事件。每监听到对应的系统事件时,就会通知 AppDelegate。
main 函数作用:
(1)创建 UIApplication 对象
(2)创建应用程序代理
(3)开启时间循环,包括应用程序的循环运行,并开始处理用户事件。
参考资料:app 启动执行顺序
40. 动画有基本类型有哪几种;表视图有哪几种基本样式。
答:动画有两种基本类型:隐式动画和显式动画。
41.Cocoa Touch 提供了哪几种 Core Animation 过渡类型?
答:Cocoa Touch 提供了 4 种 Core Animation 过渡类型,分别为:交叉淡化、推挤、显示和覆盖。
42.Quatrz 2D 的绘图功能的三个核心概念是什么并简述其作用。
答:上下文:主要用于描述图形写入哪里;
路径:是在图层上绘制的内容;
状态:用于保存配置变换的值、填充和轮廓,alpha 值等。
43.iPhone OS 主要提供了几种播放音频的方法?
答:SystemSound Services、AVAudioPlayer、Audio Queue Services、OpenAL
44. 使用 AVAudioPlayer 类调用哪个框架、使用步骤?
答:AVFoundation.framework
步骤:配置 AVAudioPlayer 对象;
实现 AVAudioPlayer 类的委托方法;
控制 AVAudioPlayer 类的对象;
监控音量水平;
回放进度和拖拽播放。
45. 原子 (atomic) 跟非原子 (non-atomic) 属性有什么区别?
(1). atomic 提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误
(2). non-atomic: 在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,那么访问器只是简单地返回这个值。
(3). 原子属性采用的是 "多读单写" 机制的多线程策略,"多读单写" 缩小了锁范围, 比互斥锁的性能好
(4). 规定只在主线程更新 UI, 就是因为如果在多线程中更新, 就需要给 UI 对象加锁, 防止资源抢占写入错误, 但是这样会降低 UI 交互的性能, 所以 ios 设计让所有 UI 对象都是非线程安全的 (不加锁), 并规定只在主线程中更新 UI, 规避多线程抢占资源问题
46.ViewController 的 didReceiveMemoryWarning 怎么被调用
答:[super didReceiveMemoryWarning];
47. 用预处理指令 #define 声明一个常数,用以表明 1 年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在这想看到几件事情:
#define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
意识到这个表达式将使一个 16 位机的整型数溢出 - 因此要用到长整型符号 L, 告诉编译器这个常数是的长整型数。
如果你在你的表达式中用到 UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
48. 写一个” 标准 " 宏 MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A)<= (B) ? (A) : (B))
#define MIN(A,B) ((A)<= (B) ? (A) : (B))
这个测试是为下面的目的而设的:
标识 #define 在宏中应用的基本知识。这是很重要的,因为直到嵌入 (inline) 操作符变为标准 C 的一部分,宏是方便产生嵌入代码的唯一方法,
对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
三重条件操作符的知识。这个操作符存在 C 语言中的原因是它使得编译器能产生比 if-then-else 更优化的代码,了解这个用法是很重要的。
懂得在宏中小心地把参数用括号括起来
我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++, b);
least = MIN(*p++, b);
结果是:
((*p++) <= (b) ? (*p++) : (*p++))
((*p++) <= (b) ? (*p++) : (*p++))
这个表达式会产生副作用,指针 p 会作三次 ++ 自增操作。
49. 关键字 const 有什么含意?修饰类呢? static 的作用, 用于类呢? 还有 externc 的作用,const 意味着 "只读",下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前两个的作用是一样,a 是一个常整型数。
第三个意味着 a 是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第四个意思 a 是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着 a 是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
结论:
关键字 const 的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。
如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用 const 的程序员很少会留下的垃圾让别人来清理的) 通过给优化器一些附加的信息,使用关键字 const 也许能产生更紧凑的代码。合理地使用关键字 const 可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少 bug 的出现。
1). 欲阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
2). 对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或二者同时指
定为 const;
3). 在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
4). 对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类的成员变量;
5). 对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为 “左值”。
50. 关键字 volatile 有什么含意? 并给出三个不同的例子。
答:一个定义为 volatile 的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是 volatile 变量的几个例子:
并行设备的硬件寄存器(如:状态寄存器)
一个中断服务子程序中会访问到的非自动变量 (Non-automatic variables)
多线程应用中被几个任务共享的变量
51. 一个参数既可以是 const 还可以是 volatile 吗?一个指针可以是 volatile 吗?
答:1). 是的。一个例子是只读的状态寄存器。它是 volatile 因为它可能被意想不到地改变。它是 const 因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个 buffer 的指针时。
52. 列举几种进程的同步机制,并比较其优缺点。
答:原子操作 信号量机制自旋锁 管程,会合,分布式系统
53. 进程之间通信的途径
答:共享存储系统消息传递系统管道:以文件系统为基础
54. 进程死锁的原因
答:资源竞争及进程推进顺序非法
55. 死锁的 4 个必要条件
答:互斥、请求保持、不可剥夺、环路
56. 死锁的处理
答:鸵鸟策略、预防策略、避免策略、检测与解除死锁
57.cocoa touch 框架
答:iPhone OS 应用程序的基础 Cocoa Touch 框架重用了许多 Mac 系统的成熟模式,但是它更多地专注于触摸的接口和优化。
UIKit 为您提供了在 iPhone OS 上实现图形,事件驱动程序的基本工具,其建立在和 Mac OS X 中一样的 Foundation 框架上,包括文件处理,网络,字符串操作等。
Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。有了 UIKit,您可以使用 iPhone OS 上的独特的图形接口控件,按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。
各色俱全的框架除了 UIKit 外,Cocoa Touch 包含了创建世界一流 iPhone 应用程序需要的所有框架,从三维图形,到专业音效,甚至提供设备访问 API 以控制摄像头,或通过 GPS 获知当前位置。
Cocoa Touch 既包含只需要几行代码就可以完成全部任务的强大的 Objective-C 框架,也在需要时提供基础的 C 语言 API 来直接访问系统。这些框架包括:
Core Animation:通过 Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。
Core Audio:Core Audio 是播放,处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。
Core Data:提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。
功能列表:框架分类
下面是 Cocoa Touch 中一小部分可用的框架:
音频和视频:Core Audio ,OpenAL ,Media Library ,AV Foundation
数据管理:Core Data ,SQLite
图形和动画:Core Animation ,OpenGL ES ,Quartz 2D
网络:Bonjour,WebKit ,BSD Sockets
用户应用:Address Book ,Core Location ,Map Kit ,Store Kit
58. 自动释放池是什么, 如何工作
答:当您向一个对象发送一个 autorelease 消息时,Cocoa 就会将该对象的一个引用放入到最新的自动释放. 它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
59.sprintf,strcpy,memcpy 使用上有什么要注意的地方。
1). sprintf 是格式化函数。将一段数据通过特定的格式,格式化到一个字符串缓冲区中去。sprintf 格式化的函数的长度不可控,有可能格式化后的字符串会超出缓冲区的大小,造成溢出。
2).strcpy 是一个字符串拷贝的函数,它的函数原型为 strcpy(char *dst, const char *src
将 src 开始的一段字符串拷贝到 dst 开始的内存中去,结束的标志符号为‘