iOS开发最新:Objective-C版本的各大厂面试题(一)
介绍有哪些设计原则,并让比较详细的说了其中开闭原则在项目中的应用?
-
单一职责原则
-
开闭原则:OC中
category
,通过runtime
添加交换方法等,都是开闭原则 -
里氏替换原则
-
接口隔离原则
-
依赖倒置原则
-
迪米特法则
-
组合/聚合复用原则
介绍自己的过往的项目经验,会结合项目问一些架构向的思考
架构是解决当项目增大,开发团队的人员越来越多,应用运营起来之后业务需求和功能需求日益增长。好的架构往往可以带来快速开发效率,和高效的代码管理。 我们可以看出我们的架构总是随着项目不断调整的,不是一尘不变的。 首先我们的架构设计应该牢记软件的设计原则。设计原则指导我们设计易理解的API设计和建立合理依赖关系。 常见的客户端架构有
-
MVC
-
MVC最大的优势就是快速开发,当项目初期,追求快速上线的时候可以使用MVC,并且苹果提供了MVC的官方支持,项目初期无疑选择MVC是最佳的。
-
MVC结构简单即使对于经验不那么丰富的开发者来讲维护起来也较为容易。
-
-
MVP
- 非常方便测试,因为view功能非常少,可以很方便测试UI细节
-
MVVM
-
MVVM的优势就是,任务均摊每部分都承担各自的责任,结构清晰更加符合软件设计原则
-
其次就是可测试性强,我们只需要测试ViewModel就能够轻易的测试UI上的问题
-
通过观察者模式,来进行属性绑定,代码量将会小的多
-
-
VIPER
-
方便测试,指责明确,更容易对每个部分进行测试。
-
设计更清晰,兼容性更强
-
同时对团队人员要求更大,代码量比其他几种架构都大,并且管理要求更高。
-
对于组件化架构,其实脱胎于前端的设计思路,在前端SPA单页面应用,路由起到了很关键的作用。路由的作用主要是保证视图和 URL 的同步。在前端的眼里看来,视图是被看成是资源的一种表现。当用户在页面中进行操作时,应用会在若干个交互状态中切换,路由则可以记录下某些重要的状态,比如用户查看一个网站,用户是否登录、在访问网站的哪一个页面。而这些变化同样会被记录在浏览器的历史中,用户可以通过浏览器的前进、后退按钮切换状态。总的来说,用户可以通过手动输入或者与页面进行交互来改变 URL,然后通过同步或者异步的方式向服务端发送请求获取资源,成功后重新绘制 UI。 那么我们把这样的思路同样可以引入iOS,android。既可以保证每个页面独立性更强,又可以保证当我们需要快速修复bug的时候可以迅速替换为web页面。 常见的路由,有MGJRouter等。
iOS
iOS编译的过程和原理
编程语言分为两种,编译语言和直译式语言
编译语言就是 必须先通过编译器生成机器码,机器码可以直接在CPU上执行,执行效率较高,代表语言有 C++,OC,Swift等
直译式语言 是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码。较编译语言来说,直译式语言效率低一些,但是编写的更灵活。
iOS中编译都是依赖于Clang(swift)
+LLVM
编译过程 预处理 -> 词法分析 -> 语法分析 -> 静态分析 -> 生成汇编指令 -> 汇编 -> 链接 -> 生成Mach-O
文件 -> dyld
动态链接 -> dSYM
iOS 静态库和动态库
静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
-
静态库:以
.a
和.framework
为文件后缀名。 -
动态库:以
.tbd
(之前叫.dylib
) 和.framework
为文件后缀名。(系统直接提供给我们的framework都是动态库!)
介绍常用属性修饰符,介绍 assign 和 weak 之间的区别。这块会延伸到内存管理相关,比如引用计数的方式。
常用属性修饰符: weak
, assign
, strong
, copy
, nonatomic
, atomic
assign
: 一般用来修饰基本的数据类型,包括基础数据类型和C数据类型。 assign
声明的属性是不会增加引用计数的,声明的属性释放后,属性就不存在了。但是,指针没有置空过程,成为了野指针,如果新的对象被分配到了这个内存地址上,又会crash
,所以一般只用来声明基本的数据类型。
weak
:弱引用,不增加引用计数。防止循环引用时使用,并且在所指向的对象被释放之后,weak
指针会被设置的为nil
。weak
引用通常是用于处理循环引用的问题,如代理及block
的使用中,相对会较多的使用到weak
。
当属性用weak修饰时,会将该指针存入一个weak
表,该表是一个hash
表,obj为键值,存储了一组obj_weak
的地址。当属性使用weak
修饰时,性能开销较大。
strong
: strong
修饰的属性一般不会自动释放,在OC中,对象默认是强指针,当属性用strong 引用计数自动加1,该指针指向的对象不会由于其他指针指向的改变而销毁。
copy
: 在我们拷贝一个对象的时候,分为深拷贝和浅拷贝。
深拷贝:对象拷贝 - 直接拷贝内容。源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1.
浅拷贝:指针拷贝 - 将指针中的地址值拷贝一份。源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retain
.
nonatomic
:非原子操作,和atomic
相对。atomic
保证系统生成的 getter
/setter
操作的完整性。注意这里只保证了getter
/setter
操作,使用atomic
并不是绝对线程安全的,当多个线程对该属性进行操作的时候,也会造成错误。
介绍 runloop 相关的知识和在实际开发中的使用情况
RunLoop
顾名思义,是运行循环。它跟线程是一一对应的,每一个线程都有一个RunLoop
,在需要的时候创建。RunLoop
的作用很简单,就是保持线程不会退出,并且处理一些事件。 Runloops是线程的基础架构部分, Cocoa
和CoreFundation
都提供了 run loop
对象方便配置和管理线程的 runloop
。每个线程,包括程序的主线程都有与之相应的 runloop
对象。
推荐文集
收录:原文地址