美文网首页iOS面试程序员
程序员用烂了却一直在用的经典面试题合集(续写)

程序员用烂了却一直在用的经典面试题合集(续写)

作者: 程晓媛闯天涯 | 来源:发表于2018-03-10 16:34 被阅读80次

    前面晓媛给大家分享过一些经典面试题,并且承诺会更新

    今天终于更新出来啦啦啦

    (一)面试题

    题一:

    OC项目里怎么混编入Swift文件?

     不管是混编还是用RN、Weex之类的混合开发模式都建议从小模块与主业务不太相关或耦合性,改动性影响度不大的地方入手。

    这里我就说OC项目里混编Swift的做法吧,毕竟这个要实用一点Swift混编OC的暂不考虑,如果用了Swift写项目了,应该坚持全用Swift不应该来混编OC,当然一些三方倒是可以的。

    一、 当我们创建一个Swift文件时,会自动有个创建桥接文件的提示,创建就行。

    二、OC怎么访问Swift类。

    Swift类放在一个 : 工程名-Swift.h的文件里,这个文件是自动生成的,不用手动创建,想在哪里访问Swift类就在哪里导入即可,当然暴力的做法是将这个文件导入到OC的pch文件里。

    三、Swift怎么访问OC类。

    把Swift想要访问到的类放在第一步创建Swfit自动生成的桥接文件里就行。

    以上只是基于之前混编时的经验来说,更加详细的请参阅苹果官方文档说明

    https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

    题二:

    单元测试、集成测试、系统测试的侧重点是什么?

           单元测试是在软件开发过程中要进行的最低级别的测试活动,在单元测试活动中,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

    集成测试,也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求,组装成为子系统或系统,进行集成测试。实践表明,一些模块虽然能够单独地工作,但并不能保证连接起来也能正常的工作。程序在某些局部反映不出来的问题,在全局上很可能暴露出来,影响功能的实现。

    系统测试是将经过测试的子系统装配成一个完整系统来测试。它是检验系统是否确实能提供系统方案说明书中指定功能的有效方法。

    (二)面试题

    一、怎么解决iOS打包成功之后,运行在iPhone上会闪退,黑屏的问题?

    关于打包之后无法安装,或者安装之后闪退的情况。

    有两种情况:

    1.证书错误.

    2.另一种就是当前的设备并不在开发者对应的账号里面。

       怎么检测当前的设备是否在开发者的证书里呢,如果你有开发者账号,直接登录app即可获得。但是没有开发者账号的情况我们该怎么办?

    以下面的ipa包为例,必须是hoc或者dev的包 

    ipa其实就是一个压缩文件,可以对齐解压。得到一个payload文件夹。 

    解压后,点击进入文件夹,然后显示包内容,可以看到里面的文件列表

    (三)面试题

    题一

    对于设计聚合SDK你有什么解决方案吗?

    例如:SharedSDK?Ping++?

    SharedSDK:聚合分享SDK

    Ping++:聚合支付SDK

    聚合地图SDK、动态切换地图,快速切换, 分析实现

    第一步:

    所有的地图特点:

    百度地图:MapView->爸爸->UIView,

    高德地图:MapView->爸爸->UIView

    而且:相同特点(共性问题), 不同特点(差异问题)

    优先解决共性问题,然后解决差异问题

    相同点:地图类型、地图坐标、地图模式等…

    不同点:细节(例如:类封装方式,结构)

    Google地图类似

     第二步:定义地图标准(统一标准)

    定义协议(所有的地图都会遵循)->IMapView

    第三步:实现具体地图

    实现百度地图、高德地图、Google地图、客户端使用的是抽象(协议),而不是使用的具体类

    注意:所有的地图都是独立,删除任意一个地图,对于整个聚合SDK没有任何影响

    实现类:BaiduMapView、GaodeMapView

    第四步:接触代码耦合问题

    如果只是当前代码,是不够的

    工厂模式->简单工厂、工厂方法、抽象工厂

    目前:工厂方法模式

    第五步:分析问题地图创建对象问题

    工厂方法模式规范

    分析角色、4个角色,

    角色一:抽象工厂->IMapFactory(地图工厂)

    只有一条流水线->专门生产地图MapView

    角色二:具体工厂->BaiduMapFactory、GaodeMapFactory

    角色三:抽象产品->IMapView

    角色四:具体产品->BaiduMapView、GaodeMapView

    目前需求:只有一个模块->基本地图显示

    工厂方法模式:核心只有一个产品抽象

    第六步:总结

    发现还是有问题,在开发中,使用多个模块、多条流水线->抽象工厂模式解决

    针对:多个产品抽象

    角色划分

    角色一:抽象工厂->IMapFactory

    角色二:具体工厂->BaiduMapFactory、GaodeMapFactory

    角色三:抽象产品A->IMapView

    角色四:抽象产品B->IMapLocation

    角色五:具体产品A1->BaiduMapView

    角色六:具体产品A2->GaodeMapView

    角色五:具体产品B1->BaiduMapLocation

    角色六:具体产品B2->GaodeMapLocation

    第七步:实现抽象工厂

    第八步:聚合SDK

    (四)面试题

    简单工厂模式实现(地图引擎)->创建工厂

    问题1

    了解过iOS中的黑魔法吗? 请解释下

    在没有一个类实现源码的情况下,想改变其中一个方法的实现,除了继承它重写和借助类别重名方法暴力抢先之处,还有更加灵活的方法Method Swizle ,类似逆向里面里的hook,挂钩,钩子的概念。

    Method swizzling 指的是改变一个已存在的选择器对应的实现的过程。OC中方法的调用能够在运行时通过改变一一通过改变类的调度表 dispatch table 中选择器到最终函数间的映射关系。

    在OC中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用OC的动态特性,可以实现在运行时偷换selector对应的方法实现。

    每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP有点类似 函数指针,指向具体的Method实现。

    我们可以利用mehod_exchangelmplementations来交换两个方法中的IMP

    我们可以利用class_replaceMethod来修改类

    我们可以利用method_setImplementation来直接设置某个方法的IMP

    归根到底,都是偷换了selector的IMP。

    问题2

    objc中向一个nil对象发送消息将会发生什么?

    在 Objective-C 中向 nil 发送消息是完全有效的——只是在运行时不会有任何作用:

    如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如:

    Person * motherInlaw = [[aPerson spouse] mother];

    如果 spouse 对象为 nil,那么发送给 nil 的消息 mother 也将返回 nil。 2. 如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者 long long 的整型标量,发送给 nil 的消息将返回0。 2. 如果方法返回值为结构体,发送给 nil 的消息将返回0。结构体中各个字段的值将都是0。 2. 如果方法的返回值不是上述提到的几种情况,那么发送给 nil 的消息的返回值将是未定义的。

    具体原因如下:

    objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。

    那么,为了方便理解这个内容,还是贴一个objc的源代码:

    // runtime.h(类在runtime中的定义)

    // 

    http://weibo.com/luohanchenyilong/

    // https://github.com/ChenYilong

    struct objc_class {

      Class isa OBJC_ISA_AVAILABILITY; //isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object

      #if !__OBJC2__

      Class super_class OBJC2_UNAVAILABLE; // 父类

      const char *name OBJC2_UNAVAILABLE; // 类名

      long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0

      long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识

      long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小

      struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表

      struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表

    struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。

      struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表

      #endif

      } OBJC2_UNAVAILABLE;

     objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,然后在发送消息的时候,objc_msgSend方法不会返回值,所谓的返回内容都是具体调用时执行的。 那么,回到本题,如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。

    今天的是面试题就分享到这里,文章会不定时更新的,敬请期待!

    作者:程晓媛闯天涯

    我是晓媛,喜欢记得关注我哦!

    相关文章

      网友评论

        本文标题:程序员用烂了却一直在用的经典面试题合集(续写)

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