iOS摸鱼周报 第十三期

iOS摸鱼周报,主要分享开发过程当中遇到的经验教训、优质的博客、高质量的学习资料、实用的开发工具等。周报仓库在这里:github.com/zhangferry/… ,若是你有好的的内容推荐能够经过 issue 的方式进行提交。另外也能够申请成为咱们的常驻编辑,一块儿维护这份周报。另可关注公众号:iOS成长之路,后台点击进群交流,联系咱们,获取更多内容。html

开发Tips

整理编辑:人魔七七ios

CocoaPods 常见操做

pod install

当咱们的工程首次使用 Cocoapods 管理第三方库的时候或者当咱们每次编辑 Podfile 文件的时候好比:添加,删除或者编辑一个 pod 库的时候,都须要执行该命令。git

  • 首次执行 pod install 命令,会下载安装新的 pod,并把每一个 pod 的版本写到 Podfile.lock 文件里。这个文件跟踪全部的 pod 库及其依赖的版本并锁定他们的版本号。
  • 在存在 Podfile.lock 的状况下执行 pod install 的时候,只解析 Podfile.lock 中没有列出的pod依赖项。1. 对于Podfile.lock 列出的版本,不须要检查 pods 是否有更新直接使用既有的版本安装。2. 对于Podfile.lock 未列出的版本,会根据Podfile 描述的版本安装。

Podfile 文件是 pod 执行的核心文件,它的解析逻辑推荐看这篇:Podfile 的解析逻辑github

pod update

pod update 能够全局升级,也能够指定 podName 单个升级。当咱们执行 pod update podName 的时候,会忽略 Podfile.lock 文件的版本,根据 Podfile 的定义尽量更新到最新的版本,并更新 Podfile.lock 文件。该命令会一样适配于 pod 库 podspec文件内部定义的依赖。 能够经过pod outdated 检测出过时的依赖版本和可升级版本。面试

对于 install 和 update 有两个经常使用参数:算法

  • --repo-update:该参数会更新全部的 repo,例如该更新了一个私有库版本,直接 install 是找不到对应版本的,咱们不想更新全部的依赖库,只想更新 对应的 repo,就可使用该指令。该参数还对应一个特有命令:pod repo update
  • --no-repo-update:update 操做会默认更新全部 repo,有时这并非必须的,且该步骤会同步 pod 公有 repo,致使比较耗时,这时就能够增长该参数,用于关闭该更新操做。

CocoaPods 使用建议

  • 推荐使用 Gemfile 管理 pod 版本,每次执行 pod 经过 bundle 进行,例如: bundle exec pod install编程

  • 工程持有管理者对项目进行 CocoaPods 初始化的时候会有一个 Podfile.lock 这个文件咱们须要归入版本控制里。小程序

  • 若是须要更新某个库到某一个版本,由项目持有管理者采用 pod update podName 的方式更新某个库到必定的版本。而后提交 Podfile.lock 和 Podfile 文件。swift

那些Bug

整理编辑:zhangferryxcode

module compiled with Swift 5.3.2 cannot be imported by the Swift 5.3 compiler: **.swiftmodule

问题背景

经过某个版本的 Xcode 生成的 Swift 库(Framework),在另外一台机器(不一样版本 Xcode)没法识别,报上述错误。

问题分析

该错误是因为编译器不兼容致使的,错误含义是由 Swift 5.3.2 编译器(编译器版本能够经过 swift --version查看)编译的module,特指 swiftmodule 文件,没法被 Swift 5.3 的编译器所识别。swiftmodule文件用于描述Swift内部的方法声明,它是二进制格式的,会根据不一样的架构生成不一样的版本。但也正由于其二进制格式的特性,没法跟随编译器的升级进行调整。这个问题对应的就是 ABI 稳定中的 module stability。这里引用喵神的一段博客内容:

ABI 稳定是使用 binary 发布框架的必要非充分条件。框架的 binary 在不一样的 runtime 是兼容了,可是做为框架,如今是依靠一个 .swiftmodule 的二进制文件来描述 API Interface 的,这个二进制文件中包含了序列化后的 AST (更准确说,是 interface 的 SIL),以及编译这个 module 时的平台环境 (Swift 编译器版本等)。

ABI 稳定并不意味着编译工具链的稳定,对于框架来讲,想要用 binary 的方式提供框架,除了 binary 自己稳定之外,还须要描述 binary 的方式 (也就是如今的 swiftmodule) 也稳定,而这正在开发中。未来,Swift 将为 module 提供文本形式的 .swiftinterface 做为框架 API 描述,而后让将来的编译器根据这个描述去“编译”出对应的 .swiftmodule 做为缓存并使用。

这一目标被称为 module stability,当达到 module stability 后,你就可使用 binary 来发布框架了。

问题解决

上面说的 module stability 已经实现了,就是能够经过 .swiftinterface 文件描述二进制包。它的实现对应一个编译参数-enable-library-evolution,在 Build Setting 里就是 Build Libraries for Distribution,咱们将其设置为 YES ,生成的 Framework 里就会包含对应的 .swiftinterface 文件,就能实现不一样版本编译器之间的兼容问题。

但到这里还没彻底结束,遇到了另外一个问题:

/*.framework/Modules/*.swiftmodule/arm64-apple-ios.swiftinterface:5:8: cannot load underlying module for 'SnapKit'

failed to build module '*' from its module interface; the compiler that produced it, 'Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)', may have used features that aren't supported by this compiler, 'Apple Swift version 5.3 (swiftlang-1200.0.29.2 clang-1200.0.30.1)
复制代码

按理说有了 swiftinterface 应该不会出现编译不兼容问题了,但仍是出现了,虽然提示内容有些不太同样,这里会多出一个内部依赖库的问题。这里查看对应版本的 swiftinterface 文件:

// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
// swift-module-flags: -target arm64-apple-ios10.0 -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -Onone -module-name ZYModule
import Foundation
import SnapKit
import Swift
import UIKit
复制代码

这里除了声明编译器信息外,还把依赖库 SnapKit 也写入了进去,因此这里猜想的隐含逻辑就是二进制库作了 Build Libraries for Distribution ,其依赖的其余库也绑定了对应的编译器版本信息,在工程里使用源码编译的 SnapKit 对于了其当前编译版本(5.3),与二进制库所生成的版本(5.3.2)不一致,因此才致使了该问题。我尝试修改项目里 Pod库 的 Build Libraries for Distribution 选项:

post_install do |installer|
  installer.pods_project.targets.each do |target|
   target.build_configurations.each do |config|
    config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
   end
  end
end
复制代码

问题获得解决,编译经过!

编程概念

整理编辑:师大小海腾zhangferry

什么是 BIOS

BIOS 全称为 Basic Input Output System,即基本输入输出系统。BIOS 是预先内置在计算机主机内部的程序,也是计算机开机后加载的第一个程序。BIOS 保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从 CMOS(是电脑主板上的一块可读写的 RAM 芯片)中读写系统设置的具体信息。

BIOS 除了键盘,磁盘,显卡等基本控制程序外,还有引导程序的功能。引导程序是存储在启动驱动器起始区域的小程序,操做系统的启动驱动器通常是硬盘。不过有时也多是 CD-ROM 或软盘。

电脑开机后,BIOS 会确认硬件是否正常运行,没有异常的话就会直接启动引导程序,引导程序的功能就是把在硬盘等记录的 OS 加载到内存中运行,虽然启动应用是 OS 的功能,但 OS 不能够本身启动本身,而是经过引导程序来启动。

制做黑苹果的时候安装的 Clover 就是一个启动程序,它经过修改 BIOS 配置,让 BIOS 首先执行它,而后由它来引导至 MacOS 的启动。

严格意义来讲 BIOS 是 IBM PC架构上的一种设计规范,Mac电脑,包括一些新型的主板都没有 BIOS 这一律念,取而代之的是 EFI/UEFI。

什么是汇编

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其余可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操做码,用地址符号或标号代替指令或操做数的地址。在不一样的设备中,汇编语言对应着不一样的机器语言指令集,经过汇编过程转换成机器指令。特定的汇编语言和特定的机器语言指令集是一一对应的,不一样平台之间不可直接移植。

汇编语言比机器语言的可读性要好,但跟高级语言比较而言,可读性仍是较差。不过采用它编写的程序具备存储空间占用少、执行速度快的特色,这些是高级语言所没法取代的。在实际应用中,是否使用汇编语言,取决于具体应用要求、开发时间和质量等方面做权衡。汇编经常使用的指令以下:

操做码 操做数 功能
mov A, B 把B的值赋给A
and A, B 把A和B同时相加,并把结果赋给A
push A 把A的值存储在栈中
pop A 从栈中读出值,并将其赋值给A
call A 调用函数A
ret 处理返回给调用源函数

什么是虚拟机

虚拟机(Virtual Machine)是指经过软件模拟的具备完整硬件系统功能的、运行在一个彻底隔离环境中的完整计算机系统。在实体计算机中可以完成的工做在虚拟机中都可以实现。在计算机中建立虚拟机时,须要将实体机的部分硬盘和内存容量做为虚拟机的硬盘和内存容量。每一个虚拟机都有独立的 CMOS、硬盘和操做系统,能够像使用实体机同样对虚拟机进行操做。

虚拟机的主要用处有:

  1. 演示环境,能够安装各类演示环境,便于作各类例子
  2. 保证主机的快速运行,减小没必要要的垃圾安装程序,偶尔使用的程序,或者测试用的程序在虚拟机上运行
  3. 避免每次从新安装,银行等经常使用工具,不常用,并且要求保密比较好的,单独在一个环境下面运行
  4. 想测试一下不熟悉或者有风险的应用,在虚拟机中随便安装和完全删除
  5. 体验不一样版本的操做系统,如 Linux、Mac 等。

虚拟机目前可分为三类:

  • 系统虚拟机,例如:VMware
  • 程序虚拟机,例如:JVM(Java Virtual Machine)
  • 操做系统层虚拟化,例如:Docker

什么是外围中断

IRQ(Interrupt Request)表明的就是中断请求。IRQ 是用来暂停当前正在运行的程序,并跳转到其余程序运行的必要机制。该机制被称为处理中断。中断处理在硬件控制中担当着重要的角色。由于若是没有中断处理,就有可能没法顺畅进行处理的状况。

从中断处理开始到请求中断的程序(中断处理程序)运行结束以前,被中断的程序(主程序)的处理是中止的。这种状况就相似于在处理文档的过程当中有电话打进来,电话就至关因而中断处理。假如没有中断处理的发生,就必须等到文档处理完成后才可以接听电话。因而可知,中断处理有着巨大的价值,就像是接听完电话后会返回原来的文档做业同样,中断程序处理完成后,也会返回到主程序中继续。

中断请求示意图

实施中断请求的是链接外围设备的 I/O 控制器,负责实施中断处理的是 CPU。

假若有多个外围设备进行中断请求的话, CPU 须要作出选择进行处理,为此,咱们能够在 I/O 控制器和 CPU 中间加入名为中断控制器的 IC 来进行缓冲。中断控制器会把从多个外围设备发出的中断请求有序的传递给 CPU。中断控制器的功能至关于就是缓冲。下面是中断控制器功能的示意图

中断控制器的功能

什么是 DMA

DMA 全称为 Direct Memory Access,即直接存储器访问。DMA 是一种内存访问机制,它是指在不经过 CPU 的状况下,外围设备直接和主存进行数据传输。磁盘等硬件设备都用到了 DMA 机制,经过 DMA,大量数据就能够在短期内实现传输,之因此这么快,是由于 CPU 做为中介的时间被节省了,下面是 DMA 的传输过程

使用 DMA 的外部设备和不使用 DMA 的外部设备

I/O 端口号、IRQ、DMA 通道能够说是识别外围设备的 3 点组合。不过,IRQ、DMA 通道并非全部外围设备都具有的。计算机主机经过软件控制硬件时所须要的信息的最低限,是外围设备的 I/O 端口号。IRQ 只对须要中断处理的外围设备来讲是必须的,DMA 通道则只对须要 DMA 机制的外围设备来讲必须的。

优秀博客

整理编辑:皮拉夫大王在此

本期博客汇总的主题是 watchdog

一、iOS watchdog (看门狗机制) -- 来自简书:Mr_Xie

先来简单了解什么是 watchdog。

二、iOS App 后台任务的坑 -- 来自cocoachina :米米狗

后台任务泄漏是致使触发 watchdog 常见状况之一,还有一种状况就是主线程卡死,文章中有介绍如何区分。

三、Addressing Watchdog Terminations

苹果的官方文档。对我我的而言,了解 scene-create 和 scene-update 的含义在排查问题过程当中起到了必定的做用。

四、你的 App 在 iOS 13 上被卡死了吗

进入实践阶段,其实咱们不多真的在主线程作大量耗时操做如网络请求等。触发 watchdog 每每是不经意的,甚至你不会怀疑你的代码有任何问题。这篇文章介绍的是 58 同城团队如何定位到剪切板形成的启动卡死。

五、iOS 稳定性问题治理:卡死崩溃监控原理及最佳实践

这篇文章是字节跳动 APM 团队早些时候发表的,是业界少有的公开介绍卡死崩溃的缘由的文章,具备很强的借鉴意义。咱们在作启动卡死优化的过程当中,文中提到的相关问题基本都有遇到,只不过在此以前并不知道什么缘由以及如何解决。因此说若是你想作卡死治理,能够参考下这篇文章。

六、面试过 500+ 位候选人以后,想谈谈面试官视角的一些期待

《iOS 稳定性问题治理:卡死崩溃监控原理及最佳实践》的做者在面试了 500+ 候选人后写的文章,有须要的同窗能够针对性的作些准备。

七、论证:iOS安全性,为何须要审核?

@iHTCboy:从辩论的视角分析 iOS 安全性,同时与 macOS 安全性进行对比,提出了让 iOS 更加安全的建议,文中同时也总结了很是多 iOS 和 macOS 安全技术小知识,可让你们在短期里快速入门和重温 Apple OS 安全性知识点。

学习资料

整理编辑:Mimosa

喵神预告:新书,开工!

喵神关于 async-swift 的书开工了。是关于Swift5.5的新特性协程,待书籍完工的第一时间咱们会经过周报再通知到你们。

New Book! Go!

30 seconds of code

地址:www.30secondsofcode.org/

该网站的口号是:「能找到知足你全部开发需求的代码片断!」,他有许多语言的经常使用代码片断(Code Snippets),例如排序算法、hex 转 rgb、时间转换等等,能让你轻松地找到各个语言的这些经常使用代码,让你的开发效率大大提高!(惋惜目前尚未 Swift 的板块🥲

工具推荐

整理编辑:zhangferry

Whatpulse

地址whatpulse.org/

软件状态:基础功能免费,高级功能付费

使用介绍

Whatpulse是一个电脑使用检测统计软件,它能够统计你天天的键盘、鼠标、网络等状况的使用详情并将其作成简单的统计表格,用于分析天天的电脑使用状况。

翻到一张以前公司电脑使用该软件将近一年的留存成果,100万+ 按键次数,使用最多的居然是删除键。。

OctoMouse

地址konsomejona.github.io/OctoMouse/i…

软件状态:免费,开源

使用介绍

该软件主要用于统计键盘及鼠标的行为信息,比较有意思的是,它对鼠标的统计会包含移动距离参数。能够试试看多久才能让鼠标移动 5km。

联系咱们

iOS摸鱼周报 第八期

iOS摸鱼周报 第九期

iOS摸鱼周报 第十期

iOS摸鱼周报 第十一期

iOS摸鱼周报 第十二期

相关文章
相关标签/搜索