美文网首页iOS 面试汇总
一个知乎iOS面试题答案

一个知乎iOS面试题答案

作者: 不吃鸡爪 | 来源:发表于2017-09-21 22:07 被阅读262次

    本文将回答知乎上iOS面试问题链接:如何面试 iOS 工程师?

    Model层:

    数据持久化存储方案有哪些?沙盒的目录结构是怎样的?各自一般用于什么场合?SQL语句问题:inner join、left join、right join的区别是什么?sqlite的优化网络通信用过哪些方式(100%的人说了AFNetworking...)如何处理多个网络请求并发的情况
    在网络请求中如何提高性能
    在网络请求中如何保证安全性

    语言与基础知识:

    内存中的栈和堆的区别是什么?那些数据在栈上,哪些在堆上?#define和const定义的变量,有什么区别什么情况下会出现内存的循环引用block中的weak self,是任何时候都需要加的么?GCD的queue,main queue中执行的代码,一定是在main thread么?
    NSOperationQueue有哪些使用方式
    NSThread中的Runloop的作用,如何使用?
    .h文件中的变量,外部可以直接访问么?(注意是变量,不是property)讲述一下runtime的概念,message send如果寻找不到相应的对象,会如何进行后续处理 ?TCP和UDP的区别是什么?
    MD5和Base64的区别是什么,各自场景是什么?
    二叉搜索树的概念,时间复杂度多少?

    架构:(我们招的不是架构师,这方面问的不多,而且从之前对APP的架构介绍里可以边听边问)

    哪些类不适合使用单例模式?即使他们在周期中只会出现一次。
    Notification的使用场景是什么?同步还是异步?
    简单介绍一下KVC和KVO,他们都可以应用在哪些场景?

    APP相关:

    如何添加一个自定义字体到工程中
    如何制作一个静态库/动态库,他们的区别是什么?
    Configuration中,debug和release的区别是什么?
    简单介绍下发送系统消息的机制(APNS) UI:
    系统如何寻找到需要响应用户操作的那个Responder
    多屏幕尺寸的适配
    UIButton的父类是什么?UILabel呢?
    push view controller 和 present view controller的区别
    描述下tableview cell的重用机制
    UIView的frame和bounds的区别是什么

    最后是几道场景题,也是我最喜欢问的:

    发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?
    实现一个第三方控件,可以在任何时候出现在APP界面最上层
    实现一个最简单的点击拖拽功能。上面那个拖拽之外,如果在手放开时,需要根据速度往前滑动呢?
    如何减小一个应用程序的尺寸?
    如何提高一个性用程序的性能?
    不同版本的APP,数据库结构变化了,如何处理?

    作者:张之诚
    链接:https://www.zhihu.com/question/19604641/answer/56306604
    来源:知乎

    下面是给出的答案,有不对的地方还请多多指教!

    一. 数据持久化存储方案有哪些?

    1. 属性列表(NSUserdefaults)
      NSUserdefaults适合存储轻量级,弱业务相关的数据,存储在应用程序的一个plist文件里,Document目录平级的/Library/Prefereces里。
    2. NSCoding
    3. 文件存储(NSFileManager)
    4. NSKeydeArchive归档存储
      又名序列化,把对象转为字节码,通过key-value以文件的形式加密存储在磁盘上
    5. 数据库
      SQlite库提供了三种方式:Single Thread, Multi Thread, Serialized(默认)
      Serialized串行队列执行所有操作,
    6. Keychain
      苹果提供的带有可逆加密的存储机制,存储密码和用户唯一标识串。

    二. 沙盒的目录结构是怎样的?各自一般用于什么场合?

    在应用的安装过程中,系统为每个单独的应用程序生成它的主目录和一些关键的子目录。苹果对沙盒的几天限制:

    1. 应用程序在自己的沙盒中运作,不能访问任何其他应用程序的沙盒;
    2. 应用之间不能共享数据;
    3. 苹果禁止任何读写沙盒以外的文件,禁止应用程序将内容写到沙盒以外的文件中;
    4. 沙盒目录里有三个文件夹:Documents、Library、Temp、AppName.app目录
      Documents-----存储;应用程序的数据文件,存储用户数据或其他定期备份的信息;
      library下有两个文件夹:Caches存储应用程序再次启动所需的信息,
      Preferences包含应用程序的偏好设置文件,不可在这更改偏好设置;
      temp存储临时文件
    5. 获取沙盒根目录方法:NSHomeDirectory获取
      获取Document路径
      NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).

    三. SQL语句问题:inner join、left join、right join的区别是什么?

    left join(左联接)返回包括左表中的所有记录和右表中联结字段相等的记录
    right join(右联接)返回包含右表中的所有记录和左表中联接字段相等的记录
    inner join (等值联接) 只返回两个表中联接字段相等的行
    select *from A left join B on A.id = B.id

    四. 在网络请求中如何提高性能?

    1.减少请求宽带:(压缩请求与响应)
    (1)使用JSON数据,高效的数据交换格式
    (2)Base64格式上传文件,对Base64数据进行压缩,减少30%的数据体积
    2.降低请求延迟:(管道化请求)
    (1)降低多个请求的延迟
    (2)在单个TCP连接上发送HTTP请求,以管道的形式发送HTTP请求,从而优化全双工TCP连接的使用。
    (3)Apache和IIS都支持管道,无需任何额外的配置。
    3.避免网络请求
    (1)在本地缓存内容避免不必要的网络流量

    五. 在网络请求中如何保证安全性

    https 和 加密

    六. 内存中的栈和堆的区别是什么?那些数据在栈上,哪些在堆上?

    栈区是由编译器自动分配释放,存放方法(函数)的参数值,局部变量的值等,栈是向低地址扩展的数据结构,是一块连续的内存区域。栈顶的地址和栈的最大容量是系统预先规定好的。
    堆由程序员分配释放,若不释放,程序结束时由OS回收,向高地址扩展的数据结构,是不连续的内存区域,
    OC对象放在堆内,非OC对象一般放在栈里面
    栈是吃了吐,堆是吃了拉
    链接:iOS 堆和栈的区别?

    七. #define和const定义的变量,有什么区别:

    1.#define在预处理阶段进行简单的替换,const在编译阶段使用;
    2.#define不做类型检查,只是简单的替换,const有数据类型会执
    行类型检查;
    3.#define不能调试, const可以调试
    4.#define大量的宏造成编译时间久
    5.#define可以定义一些简单的函数,const不可以
    6.const修饰右边的变量只读 NSString * const p

    static作用:

    1. 修饰局部变量
      (1)延长局部变量的生命周期,程序结束才会销毁
      (2)局部变量只会生成一份内存,只会初始化一次
    2. 修饰全局变量:只能在本文件中访问,修改全局变量的作用域,生命周期不会改

    extern作用:声明全局变量
    声明一个变量,不能定义变量

    static和const联合使用:声明一个静态全局只读变量
    static NSString * const name = @"name";

    extern与const联合使用
    当有多个文件使用同一个字符串常量时,可以使用extern和const组合

    新建一个全局的文件管理全局的变量
    在.m里定义 NSString *const YYTextViedBegin = @"YYTextVditing";
    在.h里应用 UIKIT_EXTERN NSString *const YYTextViewTextDidBegin;

    八. 什么情况下会出现内存的循环引用

    block,A强引用了block,block有强引用了A

    九. block中的weak self,是任何时候都需要加的么?

    只有产生循环引用了才会加

    十. GCD的queue,main queue中执行的代码,一定是在main thread么?

    对于queue中所执行的代码不一定在main thread中。如果
    queue是在主线程中创建的,那么所执行的代码就是在主线程中执行。如果是在子线程中创建的,那么就不会在main thread中执行。
    对于main queue就是在主线程中的,因此一定会在主线程中执行。获取 main queue就可以了,不需要我们创建,获取方式通过调用方法 dispatchgetmain_queue来获取。
    链接:多线程

    十一. NSOperationQueue有哪些使用方式

    链接:iOS多线程之NSOperationQueue

    与GCD的区别

    1. GCD使用方便,代码逻辑清晰,
    2. GCD是C语言构成的API,NSOperationQueue是基于GCD的Objective-C对象的封装,提供了更多的选择
    3. NSOperationQueue任务可以很方便的取消未执行的任务
    4. GCD只支持FIFO队列,NSOperation可以通过依赖关系设置操作执行顺序,控制在特定的任务执行完后才执行,GCD可以通过barrier或者group控制执行顺序,但是依赖关系复杂时,代码逻辑太复杂
    5. NSOperation支持KVO监听任务的状态(完成、执行中、取消等状态)
    6. NSOperation可以设置同一队列中任务的优先级,GCD只能区分不同队列的优先级
    7. 自定义NSOperation,封装任务逻辑,提高整个代码的复用度

    十二. NSThread中的Runloop的作用,如何使用

    runloop是一个线程里运行循环,并对收到的事件进行处理,

    1. 保持线程长时间存活
      NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
      [runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
      [runLoop run];
    2. 用于定时器

    十三. .h文件中的变量,外部可以直接访问么?(注意是变量,不是property)

    成员变量三中权限:@private, @protected, @public
    不可以,.h中的成员变量默认是@protected权限,子类可以访问,可以做权限修改,外部调用会报protected错误

    十四. 讲述一下runtime的概念,message send如果寻找不到相应的对象,会如何进行后续处理 ?

    objc向一个对象发送消息,runtime会根据对象的isa指针找到该对象实际所属类,然后在该类方法列表以及父类的方法列表中查找方法实现,如果向一个nil对象发送消息,在查找isa指针时就是0地址返回,不会出错

    十五. TCP和UDP的区别是什么?

    TCP:面向连接、传输可靠(保证数据正确性,数据顺序)、用于传输大量数据(流模式)、速度慢、建立连接需要开销较多(时间,系统资源)。
    UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。
    TCP在连接持续过程中,socket收到的数据是同一台主机发出。
    UDP只要知道接收端的IP和端口,网络可达,任何主机都可以向接受端发送数据

    十六. MD5和Base64的区别是什么,各自场景是什么

    MD5是用哈希算法(摘要算法)加密的:不可逆;密文总是16进制32位
    一般用于文件校验、密码存储
    Base64是公开的代码加密,url加密

    十七. 二叉搜索树的概念,时间复杂度多少

    采用二叉树链表作为存储结构,每个左节点均小于父节点,每个右节点均大于父节点
    时间复杂度:O(log2(n))

    十八. 哪些类不适合使用单例模式?即使他们在周期中只会出现一次。

    同一类型的对象需要在不同的用例场景发生变化

    十九. Notification的使用场景是什么?同步还是异步?

    一对多,同步

    二十. 简单介绍一下KVC和KVO,他们都可以应用在哪些场景?

    KVO:键值监听,观察某一属性的方法
    KVC:键值编码,间接访问对象的属性

    二十一. 如何添加一个自定义字体到工程中
    > 添加ttf文件,通过[UIFont fontWithName:@“字体名” size:20]使用

    二十二. 如何制作一个静态库/动态库,他们的区别是什么?

    静态库在编译时期:commond+shift+N(即新建工程)----->FrameWork&library—>Cocoa Touch Static Libiary
    动态库在运行时期:commond+shift+N(即新建工程)----->FrameWork&library—>Cocoa Touch Libiary
    区别:静态库:模块化,分工合作,避免少量改动,但是会导致大量的重复编译连接,也可以重用,注意不是共享使用 动态库:可将可执行的文件体积缩小,多个应用程序用同一份库文件,节省资源

    二十三. Configuration中,debug和release的区别是什么?

    debug :测试时期,调试版本,能设置断点,单步执行 release:发行版本,体积小,运行速度快

    二十四. 简单介绍下发送系统消息的机制(APNs)

    苹果的APNS不保证送达率,如你网络不好,在APNs那里下线,只保留最后一条消息,并告知推送数,其他消息会被APNs丢弃。

    UI:

    二十五. 系统如何寻找到需要响应用户操作的那个Responder

    系统通过调用hitTest:withEvent:接受位置参数CGPoint,从底层按照subview的顺序,测试该点在哪个view上,如果在该view上,则继续测试是否在view的subview上。。。
    响应链是从底层往上的,当没有可以处理的responder时按响应链往上回溯,一直到application也无人处理则丢弃

    二十六. 多屏幕尺寸的适配

    Autolayout、Masonry、SDAutoLayout、纯Frame计算比例

    二十七. UIButton的父类是什么?UILabel呢?

    UIControl UIView

    二十八. push view controller 和 present view controller的区别

    是否使用UINavigationController

    二十九. 描述下tableview cell的重用机制

    当cell被移出界面,进入重用池,当cell要显示时候从重用池中获取cell

    三十. UIView的frame和bounds的区别是什么

    Frame是参考父视图的坐标系,bounds参考自身坐标系

    三十一. 发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?

    GCD信号量,队列组

    1. 做法:通过dispatch_group_t来实现,将每个请求放入到Group中,将合并成大图的操作放在dispatch_group_notify中实现。
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_group_t group = dispatch_group_create();
      dispatch_group_async(group, queue, ^{ /*加载图片1 / });
      dispatch_group_async(group, queue, ^{ /
      加载图片2 / });
      dispatch_group_async(group, queue, ^{ /
      加载图片3 */ });
      dispatch_group_notify(group, dispatch_get_main_queue(), ^{
      // 合并图片
      });
    2. dispatch_group_enter()和dispatch_group_leave()

    三十二. 实现一个第三方控件,可以在任何时候出现在APP界面最上层

    三十三. 实现一个最简单的点击拖拽功能。

    三十四. 上面那个拖拽之外,如果在手放开时,需要根据速度往前滑动呢?

    三十五. 如何减小一个应用程序的尺寸?
    链接:减小iOS App或者静态库体积
    链接: iOS App 瘦身 - 以 Swift App Yep 为例

    三十六. 如何提高一个应用程序的性能?
    链接:25条提高iOS App性能的建议和技巧

    三十七. 不同版本的APP,数据库结构变化了,如何处理?
    数据库迁移

    1. 运行APP后,判断是否存在数据库,不存在则直接创建数据库,若存在取出数据库版本号进行case处理
    2. 第一次运行APP,第一次建立版本库,将数据信息存入数据库,同时保存一个当前版本加一的字段到数据库中
    3. 当APP更新时,从数据库中取出数据库中保存的版本字段,然后case执行相关方法,修改完数据结构以后,再一次将版本字段加一存到数据库中。
      链接:App升级时数据库的迁移更新

    相关文章

      网友评论

        本文标题:一个知乎iOS面试题答案

        本文链接:https://www.haomeiwen.com/subject/xzotextx.html