阅读 941

「 iOS知识小集 」2018 · 第 39 期

原文链接

上周公众号发布的以下文章:

本期知识小集的主要内容包括:

  • 忘记 AppleID 账号安全问题的解决办法
  • 对于“静态库”和“动态库”的理解总结
  • Xcode 工程添加 “动态” Framework 的几种方式
  • 不支持 __weak 修饰的类

忘记AppleID账号安全问题的解决办法

作者: 高老师很忙

悲剧的背景是这样的:有一个较早时间注册的AppleID,由于对自己记忆力的过分自信,没有备份安全问题,并之前只在网页端登录过,没有在手机端登录过,并且没有填写过手机号和其他邮箱,各种找回安全问题的路都被堵死了。在尝试了N次输入错误答案,账号被锁了N次后,只能寄希望于苹果爸爸帮我顺利登录。

联系上苹果技术支持,他们告诉我他们没有权限处理这类问题,并建议我好好回忆一下答案多尝试几次或者联系开发者支持试试;

开发者支持的电话实在太难打进去了,打了2天才打进去,得到的结果仍然是他们没有权限帮我处理,建议我开启双重认证,安全问题就自动废除了。

那么就又出现了一个新的难题,开启双重认证需要回答安全问题,感觉进入了一个死循环。。。。继续给苹果打电话,他们告诉我可以重置手机,激活的时候登录AppleID,放置几天,然后再在手机端开启双重认证,会跳过回答安全问题的步骤,问其原因,工作人员说他们也不清楚,这也不是官方做法,只是有人这样成功过,抱着试一试的心态,果然这个办法有效,以后还是好好备份才是王道呀!

对于“静态库”和“动态库”的理解总结

作者: KANGZUBIN

通常,我们的 Xcode 工程会依赖一些第三方库,包括:.a 静态库(Static Library)和 .framework 动态库(Dynamic Library)。

不过简单地把 .framework 后缀的文件称为“动态库”并不严谨,因为在 iOS/macOS 开发中,framework 又分为静态 framework动态 framework,区别如下:

  • 静态 framework:可以理解为是 .a 静态文件 + .h 公共头文件 + 资源文件 的集合,本质上与 .a 静态库是一致的;

  • 动态 framework:即真正意义上的动态库,一般包括动态二进制文件、头文件和资源文件等。

对于一个 Static Library 工程,其编译产物为 .a 静态二进制文件 + 公共 .h 头文件;

对于一个 Framework 工程,其编译的最终产物是动态库还是静态库,我们可以通过在 Build Settings -> Linking -> Mach-O Type 中进行选择设置其值为 Dynamic Library 或者 Static Library

此外,我们知道,对于一个 Mach-O 二进制文件,不管是 static 还是 dynamic,一般都包含了几种不同的处理器架构(Architectures),例如:i386, x86_64, armv7, armv7s, arm64 等。

Xcode 在编译链接时,对于静态库和动态库的处理方式是不同的。

对于静态库,在链接时(Linking Time),Xcode 会自动筛选出静态库中的不同 architecture 合并到对应处理器架构的主可执行二进制文件中;而在打包归档(Archive)时,Xcode 会自动忽略掉静态库中未用到的 architecture,例如会移除掉 i386, x86_64 等 Mac 上模拟器专用的架构。

而对于动态库,在编译打包时,Xcode 会直接拷贝整个动态 framework 文件到最终的 .ipa 包中,只有在 App 真正启动运行时,才会进行动态链接。但是苹果是不允许最终上传到 App Store Connect 后台的 .ipa 文件包含 i386, x86_64 等模拟器架构的,会报 Invalid 错误,所以对于工程中的动态 framework,我们在打 Release 正式包时,一般会通过执行命令或者脚本的方式移除掉这些 Invalid Architectures。

最后,如何在 Xcode 工程中添加这些静态/动态库呢?

对于 “.a 静态库” 和 “静态 framework” ,直接拖拽到工程中,并勾选 Copy if needed 选项即可,无需其他设置;而对于添加“动态 framework”,稍微比较麻烦,我们将在下一条小集介绍几种不同的方法。

以上,希望对你能有所帮助,不足之处,欢迎指出。

Xcode 工程添加 “动态” Framework 的几种方式

作者: KANGZUBIN

在上一条小集,我们分别介绍了 “.a 静态库”、“静态 framework” 和 “动态 framework” 的异同。

接下来我们将介绍一下,如何在 Xcode 工程中添加动态库(Dynamic Library)。

首先我们知道,对于 “.a 静态库” 和 “静态 framework”,直接把相关文件拖拽到工程中,并勾选 Copy if needed 选项即可,无需其它额外的设置;

而对于添加“动态 framework”,稍微比较麻烦,主要有以下几种方式。

PS:我们这里说的“添加动态库”是指第三方动态库,而不是像 UIKit.framework、Foundation.framework 或者 libc++ 等系统自带的动态库,对于它们的依赖添加很简单,直接在 General -> Linked Frameworks and Libraries 中点击加号搜索添加即可。

手动方式

在 Xcode 工程中选中 app 对应的 target,然后在 General -> Embedded Binaries 下点击加号,如图 1,在弹出的窗口选择 Add Other...,最后在 Finder 中选择你要添加的“动态 framework”,并勾选 Copy if needed 即可。需要注意的是,你不能直接在 Finder 中把 .framework 文件拖拽到 Embedded Binaries 中,否则会报错。

关于手动添加动态库的更多细节以及遇到问题的解决办法,可参考苹果官方的教程:《Embedding Frameworks In An App》

但是!这种方式看似很方便,其实有个坑是:我们上一条小集提到,一般动态二进制文件都会包含很多处理器架构,例如:i386, x86_64, armv7, armv7s, arm64 等,然后 Xcode 在编译链接时,对动态二进制文件是直接拷贝到 .ipa 包中,并不会像链接静态库那样筛选掉未用到 architecture,而苹果又不允许把包含 i386, x86_64 等模拟器架构的包上传到 App Store Connect 后台,会报错。因此,我们在打 Release 正式包时往往需要手动通过 lipo 命令或者编写脚本移除掉这些 Invalid Architectures。(除非你的开发工程只通过真机来调试,不准备在模拟器里运行,且添加的动态库刚好又不包含 i386、x86_64)

使用 Carthage 集成

对于通过 Carthage 集成的第三方库,在 Cartfile 文件中添加好依赖后,然后执行 carthage update 命令会帮我们生成一个个“动态 framework”,例如 AFNetworking.framework、SDWebImage.framework 等,然后把它们拖拽到工程中,详细可参考 Carthage 的 Quick Start 教程。

这里有个关键操作是,需要在 Xcode 工程的 Build Phases 中添加一个执行脚本(New Run Script Phase),并在脚本中执行如下命令:

/usr/local/bin/carthage copy-frameworks
复制代码

该命令的作用大概就是,在打包拷贝动态库时自动帮我们移除掉其中的 i386、x86_64。

使用 CocoaPods 集成

同样地,通过 CocoaPods 集成动态库时,也会在工程中自动帮我们添加一个 Shell 脚本用于做这件事,如图 2 中的 [CP] Embed Pods Frameworks,大家可以自行查阅该 Pods-xxx-frameworks.sh 脚本的内容,里面有个函数 strip_invalid_archs() 就是用于在打包时移除无用的处理器架构。

因此,我们可以把自己开发的或者他人提供的动态 framework,通过 CocoaPods 来集成到工程中:创建一个 Pods 私有 git 库(相信大家已经很熟悉了),在 git 库中添加相关动态 .frameworks 文件,然后其 Podspec 文件的写法大致如图 3 所示,最后在你的工程中 pod install 即可。

最后我们思考一个问题:“静态 framework” 和 “动态 framework” 在使用上似乎也没什么不同,而工程添加 “动态 framework” 又比较繁琐,那么在 iOS/macOS 开发中什么情况下会使用动态库呢?

不支持 __weak 修饰的类

作者: 夏天是一只猫巛

如 NSMachPort。另外自定义的类实现了 allowsWeakReference/retainWeakReference 实例方法返回 NO(默认返回YES)也不能用 __weak 修饰。allowsWeakReference 返回 NO 后,使用后会异常终止。如下图:

使用 retainWeakReference 返回 NO 后不会崩溃,但是 __weak 值为null,如下图。也可以在在该方法内部控制对象的 weak 次数。

关注我们

欢迎关注我们的公众号:iOS-Tips,也欢迎加入我们的群组讨论问题。可以公众号留言 iosflutter 等关键词获取入群方式。

关注下面的标签,发现更多相似文章
评论