面试题

作者: 今年27 | 来源:发表于2020-03-07 17:10 被阅读0次

    ios相关问题,这里也要一个博客有些记载
    https://ios.nobady.cn/Performance-optimization.html#_6-怎么检测图层混合
    消息转发
    排序有多少种:快速排序,冒泡排序,归并排序,插入排序,希尔排序
    算法(10000数组取出最大的100个,循环链)
    离屏渲染

    Category的实现原理
    Category 实际上是 Category_t的结构体,在运行时,新添加的方法,都被以倒序插入到原有方法列表同名方法的最前面,如果没有同名方法则直接插入列表尾部,所以不同的Category,添加了同一个方法,执行的实际上是最后一个。
    Category 在刚刚编译完的时候,和原来的类是分开的,只有在程序运行起来后,通过 Runtime ,Category 和原来的类才会合并到一起。

    OC与swift的区别
    https://www.jianshu.com/p/ab543aaecf50

    锁有哪些,经常用的哪种
    https://www.jianshu.com/p/1e59f0970bf5

    如何提升UITableView的流畅度
    https://www.jianshu.com/p/d5a7ffb79d9e

    https流程
    在使用HTTPS是需要保证服务端配置正确了对应的安全证书

    客户端发送请求到服务端

    服务端返回公钥和证书到客户端

    客户端接收后会验证证书的安全性,如果通过则会随机生成一个随机数,用公钥对其加密,发送到服务端

    服务端接受到这个加密后的随机数后会用私钥对其解密得到真正的随机数,随后用这个随机数当做私钥对需要发送的数据进行对称加密

    客户端在接收到加密后的数据使用私钥(即生成的随机值)对数据进行解密并且解析数据呈现结果给客户

    SSL加密建立

    并发、并行、串行、同步、异步的区别?
    https://blog.csdn.net/qq_41610418/article/details/86647967

    判断循环链表
    设置两个指针fast和slow,都指向头节点,一个一次移动两次,一个一次移动一次,如果,有一个时刻,他们两个相遇了,或者fast的next是slow(fast跑到了slow的前面),那么就代表有环。

    用runtime写一个for循环遍历

    OpenGL问题
    项目中最难的:音视频同步
    sps,pps用处,初始化解码器,解码器是哪个
    I, p, b的含义
    如何解析H264流
    h264与h265的区别
    解析H264的类的名称

    CALayer的子类有哪些
    CAEmitterLayer
    发射器层,用来控制粒子效果
    CAGradientLayer
    梯度层,颜色渐变
    CAEAGLayer
    用OpenGL ES绘制的层
    CAReplicationLayer
    用来自动复制sublayer
    CAScrollLayer
    用来管理可滑动的区域
    CAShapeLayer
    绘制立体的贝塞尔曲线
    CATextLayer
    可以绘制AttributeString
    CATiledLayer
    用来管理一副可以被分割的大图
    CATransformLayer
    用来渲染3D layer的层次结构

    如何动态绑定MVVM:

    mvc与mvvm和mvp之间的区别
    http://www.imooc.com/article/254232

    其他面试
    僵尸对象是什么,怎么解决?

    TCP与UDP的区别
    TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
    TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
    TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的。UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)。
    每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。

    说说对AutorealeasePool的理解
    App启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是 _wrapRunLoopWithAutoreleasePoolHandler()。

    第一个 Observer 监视的事件是 Entry(即将进入Loop),其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池。其 order 是-2147483647,优先级最高,保证创建释放池发生在其他所有回调之前。

    第二个 Observer 监视了两个事件: BeforeWaiting(准备进入休眠) 时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。

    对于每一个Runloop运行循环,系统会隐式创建一个Autoreleasepool对象,+ (instancetype)student中执行autorelease的操作就会将student对象添加到这个系统隐式创建的
    Autoreleasepool对象中——这回答了Autoreleasepool对象从哪里来

    当Runloop执行完一系列动作没有更多事情要它做时,它会进入休眠状态,避免一直占用大量系统资源,或者Runloop要退出时会触发执行_objc_autoreleasePoolPop()方法相当于让Autoreleasepool对象执行一次drain方法,Autoreleasepool对象会对自动释放池中所有的对象依次执行依次release操作——这回答了Autoreleasepool对象又会在何时调用[pool drain]方法

    kvo理解
    https://www.jianshu.com/p/0aa83ac521ba
    看看这篇文章说的很好

    NSString用copy与strong的区别
    当我们十分确定,要给属性NSString赋一个不可变的值时,用strong。如果使用copy来修饰属性,在进行赋值的时候,会先做一个类型判断,如果赋的值是一个不可变的字符串,则走strong的策略,进行的是浅拷贝;如果是可变的字符串,则进行深拷贝创建一个新的对象。所以如果我们确定是给属性赋值一个不可变的值,就不用copy再多去判断一遍类型,因为如果是很多的NSString属性需要赋值,会极大的增加系统开销。所以用strong在此情况下可以提升性能。

    但是很多情况下我们并不能确定要赋的值是什么类型的,所以我们还是使用copy来修饰,这样保证了安全性。因为如果赋值的可变的字符串,当它发生变化时,用strong修饰的属性的值也会跟着变化;而copy修饰的属性,则因为是深拷贝而不会变化。

    block copy strong
    之前我们需要手动的用copy属性来修饰block,让block从stack拷贝到heap,保证block在出了作用域之后也能够让block继续存在,并且以ARC的方式来决定什么时候释放在heap上的block。在2014年9月后的一次编译器优化之后,如果用strong修饰block,编译器会自动将blcok从stack拷贝到heap上。
    对于开发者来说,这就像处理普通对象一样用strong来block就行了。

    形成死锁的四个必要条件,以及如何解决死锁

    产生死锁的原因:1、竞争系统资源。2、进程的推进顺序不当。

    产生死锁的必要条件:

    1、互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。

    2、请求和保持条件:当进程因请求资源而阻塞时,对方获得的资源保持不放。

    3、不剥夺条件:进程已获得得资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。

    4、环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。

    以上四条是产生死锁的必要条件,只要发生了死锁,以上四条件必要发生。

    解决死锁的基本方法:

    预防死锁:

    1、资源一次性分配。

    2、可剥夺条件:即当某进程新的资源为满足时,释放已经占有的资源(破坏不可剥夺条件)

    3、资源有序分配法:系统给每类资源赋予一个编号,每个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)。

    避免死锁:

    预防死锁的几种策略,会严重的损坏系统性能。因此在避免死锁时,要施加较弱的限制,从而获得较满意的系统性能。由于在避免死锁的策略中,允许进程动态的申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性,若此次分配不会导致系统进入不安全状态,则将资源分配给进程,否则,进程等待。

    检测死锁:
    首先为每个进程和每个资源指定一个唯一的号码;

    然后建立资源分配表和进程等待表。

    解决死锁:

    当发现有进程死锁时,便应立即把它从死锁状态中解脱出来,常采用的方法有:

    1、剥夺资源:从其他进程剥夺足够数量的资源给死锁进程,以解决死锁状态。

    2、撤销进程:可以直接撤销死锁进程或者撤销代价最小的进程,直至有足够的资源可用,死锁状态消除为之;所谓的代价就是指优先级、运行代价,进程的重要性和价值等。

    对多线程的理解

    对SDWebImage的理解

    对NSRunloop的理解

    对RunTime的理解
    关联对象(Objective-C Associated Objects)给分类增加属性
    方法魔法(Method Swizzling)方法添加和替换和KVO实现
    消息转发(热更新)解决Bug(JSPatch)
    实现NSCoding的自动归档和自动解档
    实现字典和模型的自动转换(MJExtension)
    https://www.jianshu.com/p/6ebda3cd8052

    对ARC内存管理的理解

    webview与js交互
    https://www.jianshu.com/p/8b1ebd91b396
    JS中调用OC方法有三种方式:

    1.通过获取JSContext的方式直接调用OC方法

    2.通过继承自JSExport的方式调用delegate中的方法

    3.截取URL的方式(此种方式资料很多,就不写了)
    OC调用js代码两种方式

    通过webVIew调用 webView stringByEvaluatingJavaScriptFromString: 调用

    通过JSContext调用[context evaluateScript:];

    swift与oc混编
    https://www.jianshu.com/p/3e32bacb8da2

    Block的种类分为多少种

    触摸事件、事件传递(响应者、响应者链)、手势
    https://www.jianshu.com/p/3abd599f9f07
    https://www.jianshu.com/p/2ca56db6ab17

    UIButton事件传递的机制
    https://www.cnblogs.com/UUUUgua/p/10117381.html

    block的三种类型
    https://www.jianshu.com/p/997d144001f9

    架构模式,设计模式(胖vc,与瘦vc)

    埋点
    https://www.jianshu.com/p/79bd3b595297

    [self class]与[super class]
    当使用[self class]时,这时的self是Son,在使用objc_msgSend时,第一个参数是receiver也就是self,也是 Son* son这个实例。第二个参数,要先找到class这个方法的selector,先从Son这个类开始找,没有,然后到Son的父类 Father中去找,也没有,再去Father的父类NSObject去找,一层一层向上找之后,在NSObject的类中发现这个class方法,而 NSObject的这个class方法,就是返回receiver的类别,所以这里输出Son。

    当使用[super class]时,这时要转换成objc_msgSendSuper的方法。先构造objc_super的结构体吧,第一个成员变量就是self, 第二个成员变量是Father,然后要找class这个selector,先去superClass也就是Father中去找,没有,然后去Father 的父类中去找,结果还是在NSObject中找到了。然后内部使用函数objc_msgSend(objc_super->receiver, @selector(class)) 去调用,此时已经和我们用[self class]调用时相同了,此时的receiver还是Son* son,所以这里返回的也是Son。
    https://blog.csdn.net/Scythe666/article/details/8447638

    oc的对象布局
    1 每一个实例对象(Instance)内部都有一个isa指针,指向它的类对象,类对象存放着本对象的实例方法列表和成员变量列表。
    2 类对象(Class)内部也有一个isa指针指向元类对象(MetaClass),元类对象存放的事类方法列表
    3 类对象和元类对象内部均有一个superclass指针,指向它的父类对象。
    https://blog.csdn.net/github_36850997/article/details/85218888

    load和initialize的区别
    正常情况下(即没有在 load 方法中调用相关类方法),load 和 Initialize 方法都在实例化对象之前调用,load相当于装载方法,都在main()函数之前调用,Initialize方法都在main() 函数之后调用。
    如果在A类的 load 方法中调用 B 类的类方法,那么在调用A的Load 方法之前,会先调用一下B类的initialize 方法,但是B类的load 方法还是按照 Compile Source 顺序进行加载
    所有类的 load 方法都会被调用,先调用父类、再调用子类,多个分类会按照Compile Sources 顺序加载。但是Initialize 方法会被覆盖,子类父类分类中只会执行一个
    load 方法内部一般用来实现 Method Swizzle,Initialize方法一般用来初始化全局变量或者静态变量
    两个方法都不能主动调用,也不需要通过 super 继承父类方法,但是 Initialize 方法会在子类没有实现的时候调用父类的该方法,而 load 不会
    链接:https://www.jianshu.com/p/bd82ef5ea186

    8.简述下Objective-C中调用方法的过程

    Objective-C是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector),整个过程介绍如下:

    • objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类

    • 然后在该类中的方法列表以及其父类方法列表中寻找方法运行

    • 如果,在最顶层的父类(一般也就NSObject)中依然找不到相应的方法时,程序在运行时会挂掉并抛出异常unrecognized selector sent to XXX

    • 但是在这之前,objc的运行时会给出三次拯救程序崩溃的机会,这三次拯救程序奔溃的说明见问题《什么时候会报unrecognized selector的异常》中的说明。

    为什么需要三次握手四次挥手
    https://blog.csdn.net/zeqi1991/article/details/81582675

    app优化
    一、首页启动速度
    启动过程中做的事情越少越好(尽可能将多个接口合并)
    不在UI线程上作耗时的操作(数据的处理在子线程进行,处理完通知主线程刷新)
    在合适的时机开始后台任务(例如在用户指引节目就可以开始准备加载的数据)
    尽量减小包的大小
    优化方法:
    量化启动时间
    启动速度模块化
    辅助工具(友盟,听云,Flurry)
    二、页面浏览速度
    json的处理(iOS 自带的NSJSONSerialization,Jsonkit,SBJson)
    数据的分页(后端数据多的话,就要分页返回,例如网易新闻,或者 微博记录)
    数据压缩(大数据也可以压缩返回,减少流量,加快反应速度)
    内容缓存(例如网易新闻的最新新闻列表都是要缓存到本地,从本地加载,可以缓存到内存,或者数据库,根据情况而定)
    延时加载tab(比如app有5个tab,可以先加载第一个要显示的tab,其他的在显示时候加载,按需加载)
    算法的优化(核心算法的优化,例如有些app 有个 联系人姓名用汉语拼音的首字母排序)
    三、操作流畅度优化:
    Tableview 优化(tableview cell的加载优化)
    ViewController加载优化(不同view之间的跳转,可以提前准备好数据)
    四、数据库的优化:
    数据库设计上面的重构
    查询语句的优化
    分库分表(数据太多的时候,可以分不同的表或者库)
    五、服务器端和客户端的交互优化:
    客户端尽量减少请求
    服务端尽量做多的逻辑处理
    服务器端和客户端采取推拉结合的方式(可以利用一些同步机制)
    通信协议的优化。(减少报文的大小)
    电量使用优化(尽量不要使用后台运行)
    六、非技术性能优化
    产品设计的逻辑性(产品的设计一定要符合逻辑,或者逻辑尽量简单,否则会让程序员抓狂,有时候用了好大力气,才可以完成一个小小的逻辑设计问题)
    界面交互的规范(每个模块的界面的交互尽量统一,符合操作习惯)
    代码规范(这个可以隐形带来app 性能的提高,比如 用if else 还是switch ,或者是用!还是 ==)
    code review(坚持code Review 持续重构代码。减少代码的逻辑复杂度)
    日常交流(经常分享一些代码,或者逻辑处理中的坑)

    面试题 1-100个数的数组随机打乱
    int a[] = {3,5,7,1,4};
    int b[5];
    int len=5; // 全集元素数量
    srand( (unsigned int)time(NULL)); // 摇号机准备
    for(int i= 0;i < 5;i++) // 从全集开始摇号,直至只剩一个
    {
    int cur = (rand()%len); // 在剩余集合中摇号
    b[i] = a[cur];
    len --;
    for (int i = cur; i < len; i++) {
    a[cur] = a[cur + 1];//每次从a中拿取一个数之后就拿掉这个数字
    cur++;
    }
    printf("%d", b[i]);
    }

    苹果内购注意
    https://blog.csdn.net/weixin_40876113/article/details/80772359

    gcd与NSOperation的区别
    NSOperation可以停止已经start的线程吗?如何停止?

    iOS崩溃日志分析
    对于偶然崩溃日志的理解:重复过程,定位代码,考虑是不是内存泄漏或者野指针。考虑是release包与debug包之间的差距

    为什么说TCP是安全的,UDP是不安全的
    因为TCP丢包之后,会做数据校验,然后重传数据。接收方每收到一个数据包就发送一次确认,发送方设置定时器,如果定时没有收到接收确认就重传。有两种,一种是丢多少重传多少,一种是从丢弃的地方重新传送数据,一般是后面一种。并且针对传输的流量,TCP会做限制,尽量保证网络的最大传输效率,保证接受方稳定接受。

    UITableViewCell的重用机制
    首先系统会创建一个绑定重用标识符的重用池.在重用池中有着这样两个队列集合,分别存放着正在使用的cell和等待使用的cell,A1已经滑动到屏幕区域外,这时候系统会把相应的cell从使用队列中删除这个cell,放到等待使用的队列中去.以便于下一次使用,这样循环往复的操作就实现了tableViewCell的重用.

    你的优势是什么
    最好是从案例回答,比如你做过什么项目,解决的什么困难,你是怎么想到的

    爬楼梯
    https://blog.csdn.net/Jet_Green/article/details/81631028

    afnetworking的底层,AFNetworking2.0余AFNetworking3.0的区别
    afnetworking如何实现断点续传
    NSString *rangeString = [NSString stringWithFormat:@"Bytes=%lld-%lld",FromB,ToB];
    [request setValue:rangeString forHTTPHeaderField:@"Range"];

    HTTPS是如何进行加密传输的

    UITableViewCell怎么缓存高度

    主队列与主线程哪种情况下不统一

    对于af,sdweb,masonry框架的阅读

    DNS劫持、锁、HTTPS、静态库动态库等

    组件化开发

    相关文章

      网友评论

          本文标题:面试题

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