美文网首页
iOS面试题总结

iOS面试题总结

作者: 超级英雄悟空 | 来源:发表于2017-06-25 10:06 被阅读15次

    1.日常开发中造成程序崩溃有哪些?如何避免、解决?
    答:服务器返回的数据格式原因。导致崩溃,进行容错处理,进行相应判断再处理数据。例如:创建字典的时候value为nil。
    数组越界问题。采用runtime替换成自己的方法、

    2.runloop和线程有什么关系?
    答:主线程的run loop默认是启动的, 子线程的runloop默认是不开启的,需要我们自己手动开启循环,,runloop执行完毕之后,就会进入休眠 , 只有在某个情况下触发了,才会再次调用。

    3.使用系统的block api,是否也考虑引用循环问题?
    答:系统的某些block api中,UIView的block版本写动画时不需要考虑。在ARC环境下,使用__weak关键字,可以避免循环引用

    4.异常检测的机制是什么?如何实现?
    答:NSException

    5.socket连接
    答:Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。建立网络通信连接至少要一对端口号(socket)。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。

    20161129011241557.png

    手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。建立起一个TCP连接需要经过“三次握手”:
    第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
    握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。

    HTTP协议即超文本传送协议(HypertextTransfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
    HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
    1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
    2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

    6.描述应用程序的启动顺序
    答:①.先加载Main函数

    ②.在Main函数里的 UIApplicationMain方法中,创建Application对象 创建Application的Delegate对象

    ③.创建主循环,代理对象开始监听事件

    ④.启动完毕会调用 didFinishLaunching方法,并在这个方法中创建UIWindow

    ⑤.设置UIWindow的根控制器是谁

    ⑥.如果有storyboard,会根据info.plist中找到应用程序的入口storyboard并加载箭头所指的控制器

    ⑦.显示窗口

    技术
    基础

    1. 为什么说Objective-C是一门动态的语言?
    答:oc的多态性让其拥有动态性,objective-c的动态性,让程序在运行时判断其该有的行为。它的动态性主要体现在3个方面:
    1.动态类型:如id类型。实际上静态类型因为其
    固定性和可预知性而使用的特别广泛。静态类型是强类型,动态类型是弱类型,运行时决定接收者。
    2.动态绑定:让代码在运行时判断需要
    调用什么方法,而不是在编译时。与其他面向对象语言一样,方法调用和代码并没有在编译时连接在一起,而是在消息发送时才进行连接。运行时决定调用哪个方法。
    3.动态载入。让程序在运行时添加代码模块以及其他资源。用户可以根据需要执行一些可执行代码和资源,而不是在启动时就加载所有
    组件。可执行代码中可以含有和程序运行时整合的新类。

    2.讲一下MVC和MVVM,MVP?
    答:MVC(模型-视图-控制器),M是指业务数据, V是指用户界面, C则是控制器. 在具体的业务场景中, C作为M和V之间的连接, 负责获取输入的业务数据, 然后将处理后的数据输出到界面上做相应展示, 另外, 在数据有所更新时, C还需要及时提交相应更新到界面展示,因为M和V之间是完全隔离的, 所以在业务场景切换时, 通常只需要替换相应的C, 复用已有的M和V便可快速搭建新的业务场景. MVC因其复用性, 大大提高了开发效率,但随着业务数据的复杂,大量的代码被放进viewcontroller,导致很难测试。

    MVVM: 模型-视图-视图模型(Model-View-ViewModel),view和view controller正式联系在一起,我们把它们视为一个组件。视图view仍然不能直接引用模型Model,当然controller也不能。相反,他们引用视图模型view Model。view Model是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。

    MVP:M : 逻辑Model层 V : 视图层 P : protocol协议层,它将业务逻辑和业务展示也做了一层隔离, 对应的就变成了MVCP. M和V功能不变, 原来的C现在只负责布局, 而所有的逻辑全都转移到了P层.

    3.为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别?
    答:weak:指明该对象并不负责保持delegate这个对象,delegate这个对象的销毁由外部控制
    strong:该对象强引用delegate,外界不能销毁delegate对象,会导致循环引用(Retain Cycles)
    代理用weak为了防止循环引用

    delegate控制的是UI,是上层的东西;而datasource控制的是数据。他们本质都是回调,只是回调的对象不同

    block 更轻型,使用更简单,能够直接访问上下文,这样类中不需要存储临时数据,使用 block 的代码通常会在同一个地方,这样读代码也连贯。delegate 更重一些,需要实现接口,它的方法分离开来,很多时候需要存储一些临时数据,另外相关的代码会被分离到各处,没有 block 好读。
    如果这个回调是一个不定期触发,或者会多次触发的,那么 Delegation 应该更适合;如果这个回调是一个一次性的,并且和调用方法是单线性关系的,那么 Block 应该更适合。

    4.属性的实质是什么?包括哪几个部分?属性默认的关键字都有哪些?@dynamic关键字和@synthesize关键字是用来做什么的?
    答:

    5.NSString为什么要用copy关键字,如果用strong会有什么问题?(注意:这里没有说用strong就一定不行。使用copy和strong是看情况而定的)
    6.如何令自己所写的对象具有拷贝功能?
    7.可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?
    8.为什么IBOutlet修饰的UIView也适用weak关键字?
    9.nonatomic和atomic的区别?atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?
    10.UICollectionView自定义layout如何实现?
    11.用StoryBoard开发界面有什么弊端?如何避免?
    12.进程和线程的区别?同步异步的区别?并行和并发的区别?
    线程间通信?

    答:一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的所有线程共享当前进程所拥有的资源。

    任务的执行分为同步和异步,同步执行是发出一个调用时,等待执行完返回,才继续往下执行,异步执行是发出调用之后立即返回,继续往下执行.(例子: 同步: 你打电话问书店老板有没有 <<多线程编程>> 这本书,如果是同步通信机制.书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果).这其中你电话不挂断.(等待返回结果)接收不到返回结果,不继续下面的操作. 异步:书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果).你继续该干哈干哈.等老板然后查好了,他会主动打电话给你,在这里老板通过“回电”这种方式来回调.

    并行:三个人同时吃一个馒头(指两个或两个以上事件或活动在同一时刻发生。在多道程序环境下,并行性使多个程序同一时刻可在不同CPU上同时执行。)
    并发:一个人同时吃三个馒头(指两个或两个以上的事件或活动在同一时间间隔内发生。并发的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序之间多路复用,并发性是
    对有限物理资源强制行使多用户共享以提高效率。)

    13.GCD的一些常用的函数?(group,barrier,信号量,线程同步)
    14.如何使用队列来避免资源抢夺?
    15.数据持久化的几个方案(fmdb用没用过)
    答:plist文件(属性列表)
    preference(偏好设置)
    NSKeyedArchiver(归档)
    SQLite 3(FMDB)
    CoreData

    16.说一下AppDelegate的几个方法?从后台到前台调用了哪些方法?第一次启动调用了哪些方法?从前台到后台调用了哪些方法?
    答: //当程序第一次运行并且将要显示窗口的时候执行,在该方法中我们完成的操作(1)创建一个窗口对象,并且将窗口对象指定为程序的主窗口。(2)我们写的代码也在该方法中。

    • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
      self.window.backgroundColor = [UIColor whiteColor];
      [self.window makeKeyAndVisible]; //指定为主窗口
      return YES;
      }

    //程序进入后台的时候首先执行程序将要取消活跃该方法。

    • (void)applicationWillResignActive:(UIApplication *)application {
      //在该方法中我们经常用来暂停正在执行的任务,让时间计时器失效。如果是游戏需要暂停游戏的运行。
      }
      //该方法当应用程序进入后台的时候调用
    • (void)applicationDidEnterBackground:(UIApplication *)application {
      //在该方法中经常用来释放一些公共资源,保存用户数据,使时间计时器失效,保存足够的状态信息用来恢复应用程序之前的状态。
      //当应用程序支持后台运行的时候,该方法会取代applicationWillTerminate:方法
      }

    //当程序进入将要前台的时候调用

    • (void)applicationWillEnterForeground:(UIApplication *)application {
      //该方法中我们经常用来取消在程序进入后台的时候执行的操作。
      }
      //应用程序已经变得活跃(应用程序的运行状态)
    • (void)applicationDidBecomeActive:(UIApplication *)application {
      //重启之前暂停或者之前根本没有运行的任务。如果程序之前在后台,必要的时候需要做界面的刷新操作。
      }

    //当程序将要退出的时候调用,如果应用程序支持后台运行,该方法被applicationDidEnterBackground:替换

    • (void)applicationWillTerminate:(UIApplication *)application {
      }

    17.NSCache优于NSDictionary的几点?
    答:NSCache胜过NSDictionary之处在于,当系统资源将要耗尽时,它可以自动删减缓存。如果采用普通的字典,那么就要自己编写挂钩,在系统发出“低内存”通知时手工删减缓存。

    NSCache并不会“拷贝”键,而是会“保留”它。此行为用NSDictionary也可以实现,然而需要编写相当复杂的代码。NSCache对象不拷贝键的原因在于:很多时候,键都是不支持拷贝操作的对象来充当的。因此,NSCache不会自动拷贝键,所以说,在键不支持拷贝操作的情况下,该类用起来比字典更方便。另外,NSCache是线程安全的,而NSDictionary则绝对不具备此优势。

    18.知不知道Designated Initializer?使用它的时候有什么需要注意的问题?
    答:是一个很有用的宏,充分发挥编译器的特性帮我们找出初始化过程中可能存在的漏洞,增强代码的健壮性。
    (1)每个类的正确初始化过程应当是按照从子类到父类的顺序,依次调用每个类的Designated Initializer。并且用父类的Designated Initializer初始化一个子类对象,也需要遵从这个过程。
    (2)如果子类指定了新的初始化器,那么在这个初始化器内部必须调用父类的Designated Initializer。并且需要重写父类的Designated Initializer,将其指向子类新的初始化器。
    (3)你可以不自定义Designated Initializer,也可以重写父类的Designated Initializer,但需要调用直接父类的Designated Initializer。
    (4)如果有多个Secondary initializers(次要初始化器),它们之间可以任意调用,但最后必须指向Designated Initializer。在Secondary initializers内不能直接调用父类的初始化器。
    (5)如果有多个不同数据源的Designated Initializer,那么不同数据源下的Designated Initializer应该调用相应的[super (designated initializer)]。如果父类没有实现相应的方法,则需要根据实际情况来决定是给父类补充一个新的方法还是调用父类其他数据源的Designated Initializer。比如UIView的initWithCoder调用的是NSObject的init。
    (6)需要注意不同数据源下添加额外初始化动作的时机。
    详解:http://blog.jobbole.com/65762/

    19.实现description方法能取到什么效果?
    答:使用NSLog 和 %@ 输出某个对象时,就会调用这个对象的 description 方法,它的返回值就是 NSString 字符串类型

    20.objc使用什么机制管理对象内存?
    答:1).MRC(manual retain-release)手动内存管理2).ARC(automatic reference counting)自动引用计数

    相关文章

      网友评论

          本文标题:iOS面试题总结

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