写点什么

iOS 面试策略之系统框架 - 网络、推送与数据处理

用户头像
iOSer
关注
发布于: 2021 年 05 月 18 日
iOS 面试策略之系统框架-网络、推送与数据处理

如果说移动时代的前身是什么,我想一个可能的答案就是网络时代。网络的兴起,让所有设备相连成为了可能,也催生了电商、社交、搜索等多个领域的商业巨头。而移动时代,则是网络时代的必然延伸,它代表着更便捷、更广阔、更深入的连接。


在这个背景之下,我们所开发的 App 或多或少会与网络相连。或是拉取服务器端数据来更新 UI,或是通过网络推送自己的消息,或是在手机端删除自己曾经的照片,或是打开音乐播放应用下载自己喜欢的歌曲。如何请求、接收、处理、发送数据,就是我们这节要讨论的内容。

计算机理论

1.谈谈 HTTP 中 GET 与 POST 的区别

关键词:#方向 #类型 #参数位置


  • 从方向上来看,GET 是从服务器端获取信息,POST 是向服务器端发送信息。

  • 从类型上来看,GET 处理静态和动态内容,POST 只处理动态内容。

  • 从参数位置来看,GET 的参数在其 URI 里,POST 的参数在它的包体里:从这个角度来看,POST 比 GET 更加安全隐秘。

  • GET 可以被缓存,可以被储存在浏览器历史中,其内容理论上有长度限制;POST 在这 3 点上恰恰相反。

2.谈谈 Session,Token,Cookie 的概念

关键词:#用户认证 #客户端 #服务器端


  • Session 是服务器端用来认证、追踪用户的数据结构。它通过判断客户端传来的信息确定用户,确定用户的唯一标识是客户端传来的 Session ID。

  • Token 是服务器端生成的一串字符串,是客户端进行请求的令牌、服务器端用以确定用户的唯一标识。Session ID 就经常被用作 Token 来使用。Token 的出现避免了服务器频繁的查询用户名和密码,降低了数据库的查询压力。

  • Cookie 是客户端保存用户信息的机制。初次会话 HTTP 协议会在 Cookie 里记录一个 Session ID ,之后每次把 Session ID 发给服务器端。

  • Session 一般用于用户验证。它默认存在服务器的一个文件里,当然内存、数据库里也可以存储。

  • 若是客户端禁用了 Cookie,客户端会用 URL 重写技术,即会话时在 URL 的末尾加上 Session ID,并发送给服务器端。

3.在一个 HTTPS 连接的网站里,输入账号密码点击登录后,到服务器返回这个请求前,中间经历了什么

关键词:#锁 #客户端 #服务器端


**1) 客户端打包请求。**包括 url,端口啊,你的账号密码等等。账号密码登陆应该用的是 Post 方式,所以相关的用户信息会被加载到 body 里面。这个请求应该包含三个方面:网络地址,协议,资源路径。注意,这里是 HTTPS,就是 HTTP + SSL / TLS,在 HTTP 上又加了一层处理加密信息的模块(相当于是个锁)。这个过程相当于是客户端请求钥匙。


**2) 服务器接受请求。**一般客户端的请求会先发送到 DNS 服务器。 DNS 服务器负责将你的网络地址解析成 IP 地址,这个 IP 地址对应网上一台机器。这其中可能发生 Hosts Hijack 和 ISP failure 的问题。过了 DNS 这一关,信息就到了服务器端,此时客户端会和服务器的端口之间建立一个 socket 连接,socket 一般都是以 file descriptor 的方式解析请求。这个过程相当于是服务器端分析是否要向客户端发送钥匙模板。


**3) 服务器端返回数字证书。**服务器端会有一套数字证书(相当于是个钥匙模板),这个证书会先发送给客户端。这个过程相当于是服务器端向客户端发送钥匙模板。


**4) 客户端生成加密信息。**根据收到的数字证书(钥匙模板),客户端会生成钥匙,并把内容锁上,此时信息已经加密。这个过程相当于客户端生成钥匙并锁上请求。


**5) 客户端发送加密信息。**服务器端会收到由自己发送出去的数字证书加锁的信息。 这个时候生成的钥匙也一并被发送到服务器端。这个过程是相当于客户端发送请求。


**6) 服务器端解锁加密信息。**服务器端收到加密信息后,会根据得到的钥匙进行解密,并把要返回的数据进行对称加密。这个过程相当于服务器端解锁请求、生成、加锁回应信息。


**7) 服务器端向客户端返回信息。**客户端会收到相应的加密信息。这个过程相当于服务器端向客户端发送回应。


**8) 客户端解锁返回信息。**客户端会用刚刚生成的钥匙进行解密,将内容显示在浏览器上。


如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群931 542 608来获取一份详细的大厂面试资料为你的跳槽多添一份保障。


整个过程的流程图如下:



iOS 网络请求

4.请说明并比较以下类:URLSessionTask,URLSessionDataTask,URLSessionUploadTask,URLSessionDownloadTask

关键词:#URLSession


  • URLSessionTask 是个抽象类。通过实现它可以实例化任意网络传输任务,诸如请求、上传、下载任务。它的暂停(cancel)、继续(resume)、终止(suspend)方法有默认实现

  • URLSessionDataTask 负责 HTTP GET 请求。它是 URLSessionTask 的具体实现。一般用于从服务器端获取数据,并存放在内存中。

  • URLSessionUploadTask 负责 HTTP Post/Put 请求。它继承了 URLSessionDataTask。一般用于上传数据。

  • URLSessionDownloadTask 负责下载数据。它是 URLSessionTask 的具体实现。它一般将下载的数据保存在一个临时的文件中;在 cancel 后可将数据保存,并之后继续下载。


它们之间的关系如下图:



5. 什么是 Completion Handler?

关键词:#闭包


Completion Handler 一般用于处理 API 请求之后的返回数据。


当 URLSessionTask 结束之后,无论成功或是报错,Completion Handler 一般都会接受 3 个参数:Data, URLResponse,Error,注意这 3 个参数都是 Optional。


在 Swift 中,Completion Handler 必须标明 @escaping。因为它总是在 API 请求之后才执行,也就是说方法已经返回才会涉及 Completion Handler,是个经典的逃逸闭包情况。

6. 代码实战:设计一个方法,给定 API 的网址,返回用户数据

关键词:#URLSessionDataTask


这道题目考察的是 URLSessionDataTask 的基本用法。下面是一种最简单粗暴的写法:


func queryUser(url: String, completion: @escaping (_ user: User?, _ error : Error?) -> Void)) {
guard let url = URL(string: url) else { return }
URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { DispatchQueue.main.async { completion(nil, error) } return } else if let data = data, let response = response as? HTTPURLResponse { DispatchQueue.main.async { completion(convertDataToUser(data), nil) } } else { DispatchQueue.main.async { completion(nil, NSError(“invalid response”)) } } }.resume()}
复制代码


上面的写法有很多问题,其中最主要的是:


  • url 出错处理不当。应该返回错误信息以方便日后调试,而不是应该 return

  • 用 URLSession 的单例不妥。这样每次请求创建一个 dataTask 是一种浪费,同时短时间内多次请求会不必要的造成服务器压力。正确的处理方法应该是每次请求都取消上一次请求(无论有无完成)。

  • 代码重复冗余。代码中多次用到了切换至主线程并调用闭包的过程。实际上我们可以将整个方法扩展为一个类,然后将返回值与成员变量结合起来使用。


除了以上 3 点,我们还可以进一步修正代码,增强其可读性,并完善其逻辑。修改后的代码如下:


enum QueryError: String {  case InvaldURL = “Invalid URL”,  case InvalidResponse = “Invalid response”}
class QueryService { typealias QueryResult = (User?, String?) -> Void
var user: User? var errorMessage: String?
let defaultSession = URLSession(configuration: .default) var dataTask: URLSessionDataTask?
func queryUsers(url: String, completion: @escaping QueryResult) { dataTask?.cancel()
guard let url = URL(string: url) else { DispatchQueue.main.async { completion(user, QueryError.InvalidURL) } return }
dataTask = defaultSession.dataTask(with: url) { [weak self] data, response, error in defer { self?.dataTask = nil } if let error = error { self?.errorMessage = error.localizedDescription } else if let data = data, let response = response as? HTTPURLResponse, response.statusCode == 200 { self?.user = convertDataToUser(data) } else { self?.errorMessage = QueryError.InvalidResponse }
DispatchQueue.main.async { completion(self?.user,self?.errorMessage) } }.resume() }}
复制代码


上面的修改方法主要针对一些硬伤。如果配合 Swift 的面向协议的编程来实现该 API,整个代码会更加灵活。

信息推送

7. iOS 开发中本地消息通知的流程是怎样的?

关键词:#UserNotifications


UserNotifications 框架是苹果针对远程和本地消息通知的框架。其流程主要分 4 步:


**1) 注册。**通过调用 requestAuthorization 这个方法,通知中心会向用户发送通知许可请求。在弹出的 Alert 中点击同意,即可完成注册。**2) 创建。**首先设置信息内容 UNMutableNotificationContent 和触发机制 UNNotificationTrigger ;然后用这两个值来创建 UNNotificationRequest;最后将 request 加入到当前通知中心 UNUserNotificationCenter.current() 中。**3) 推送。**这一步就是系统或者远程服务器推送通知。伴随着一声清脆的响声(或自定义的声音),通知对应的 UI 显示到手机界面的过程。**4) 响应。**当用户看到通知后,点击进去会有相应的响应选项。设置响应选项是 UNNotificationAction 和 UNNotificationCategory。


如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群931 542 608来获取一份详细的大厂面试资料为你的跳槽多添一份保障。


加分回答:远程推送的流程与本地推送大同小异,不同的是第 2 步创建,参数内容和消息创建都在服务器端完成,而不是在本地完成。

8.iOS 开发中远程消息推送的原理是怎样的?

关键词: #APNs Server


回答这道题目的关键在于理清 iOS 系统,App,APNs 服务器,以及 App 对应的客户端之间的关系。具体来说就是:


  1. App 向 iOS 系统申请远程消息推送权限。这与本地消息推送的注册是一样的;

  2. iOS 系统向 APNs(Apple Push Notification Service) 服务器请求手机的 device token,并告诉 App,允许接受推送的通知;

  3. App 将手机的 device token 传给 App 对应的服务器端;

  4. 远程消息由 App 对应的服务器端产生,它会先经过 APNs;

  5. APNs 将远程通知推送给响应手机。


具体的流程图如下:



数据处理

9.iOS 开发中如何实现编码和解码?

关键词: #Encodable #Decodable


编码和解码在 Swift 4 中引入了 Encodable 和 Decodable 这两个协议,而 Codable 是 Encodable 和 Decodable 的合集。在 Swift 中,Enum,Struct,Class 都支持 Codable。一个最简单的使用如下:


enum Gender: String, Codable {  case Male = “Male”  case Female = “Female”}
class User: Codable { let name: String let age: Int let gender: Gender
init(name: String, age: Int, gender: Gender) { (self.name, self.age, self.gender) = (name, age, gender) }}
复制代码


这样定义完成之后,我们就可以轻易的在 User 及其对应 JSON 数据进行编码和解码,示范代码如下:


let userJsonString = """{        "name": "Cook",        "age": 58,        "gender": "Male"}"""
// 从JSON解码到实例if let userJSONData = userJsonString.data(using: .utf8) { let userDecode = try? JSONDecoder().decode(User.self, from: userJSONData)}
//从实例编码到JSONlet userEncode = User(name: "Cook", age: 58, gender: Gender.Male)let userEncodedData = try? JSONEncoder().encode(userEncode)
复制代码


追问:假如 JSON 的键值和对象的属性名不匹配该怎么办?


可以在对象中定义一个枚举(enum CodingKeys: String, CodingKey),然后将属性和 JSON 中的键值进行关联。


追问:假如 class 中某些属性不支持 Codable 该怎么办?


将支持 Codable 的属性抽离出来定义在父类中,然后在子类中配合枚举(enum CodingKeys),将不支持的 Codable 的属性单独处理。

10.谈谈 iOS 开发中数据持久化的方案

关键词: #plist #Preference #NSKeyedArchiver #CoreData


数据持久化就是将数据保存在硬盘中,这样无论是断网还是重启,我们都可以访问到之前保存的数据。iOS 开发中有以下几种方案:


  • **plist。**它是一个 XML 文件,会将某些固定类型的数据存放于其中,读写分别通过 contentsOfFile 和 writeToFile 来完成。一般用于保存 App 的基本参数。

  • **Preference。**它通过 UserDefaults 来完成 key-value 配对保存。如果需要立刻保存,需要调用 synchronize 方法。它会将相关数据保存在同一个 plist 文件下,同样是用于保存 App 的基本参数信息。

  • **NSKeyedArchiver。**遵循 NSCoding 协议的对象就就可以实现序列化。NSCoding 有两个必须要实现的方法,即父类的归档 initWithCoder 和解档 encodeWithCoder 方法。存储数据通过 NSKeyedArchiver 的工厂方法 archiveRootObject:toFile: 来实现;读取数据通过 NSKeyedUnarchiver 的工厂方法 unarchiveObjectwithFile:来实现。相比于前两者, NSKeyedArchiver 可以任意指定存储的位置和文件名。

  • **CoreData。**前面几种方法,都是覆盖存储。修改数据要读取整个文件,修改后再覆盖写入,十分不适合大量数据存储。CoreData 就是苹果官方推出的大规模数据持久化的方案。它的基本逻辑类似于 SQL 数据库,每个表为 Entity,然后我们可以添加、读取、修改、删除对象实例。它可以像 SQL 一样提供模糊搜索、过滤搜索、表关联等各种复杂操作。尽管功能强大,它的缺点是学习曲线高,操作复杂。


以上几种方法是 iOS 开发中最为常见的数据持久化方案。除了这些以外,针对大规模数据持久化,我们还可以用 SQLite3、FMDB、Realm 等方法。相比于 CoreData 和其他方案,Realm 以其简便的操作和丰富的功能广受很多开发者青睐。同时大公司诸如 Google 的 Firebase 也有离线数据库功能。其实没有最佳的方案,只有最合适的方案,应该根据实际开发的 App 来挑选合适的持久化方案。

小编推荐阅读

文章到这里就结束了,感谢你的观看,只是有些话想对读者们说说:

iOS 开发人群越来越少,说实在的,每次在后台看到一些读者的回应都觉得很欣慰,至少你们依然坚守 iOS 技术岗…为了感谢读者们,我想把我收藏的一些编程干货贡献给大家,回馈每一个读者,希望能帮到你们。


干货主要有:


① iOS 中高级开发必看的热门书籍(经典必看)


② iOS 开发技术进阶教学视频


③ BAT 等各个大厂 iOS 面试真题+答案.PDF 文档


④ iOS 开发中高级面试"简历制作"指导视频


如果你用得到的话可以直接拿走;如何获取,具体内容请转看-我的GitHub


我的:GitHub地址

用户头像

iOSer

关注

微信搜索添加微信 mayday1739 进微信群哦 2020.09.12 加入

更多大厂面试资料进企鹅群931542608

评论

发布
暂无评论
iOS 面试策略之系统框架-网络、推送与数据处理