observeOn vs. subscribeOn【译】
iOS 页面卡死,但并不是 Crash 的问题解决
最近在做的一款 App 测试中出现了一个非常诡异的问题,偶尔的界面卡死,但是又并不是 Crash,没有抛出任何异常,把 App 切到后台然后在点开又恢复了,只不过转场的时候十分诡异,似乎完全没有动画,转场背景还是黑的。
什么原因呢?死循环?不可能;内存泄漏?也不可能?😂;手势冲突?很有可能🧐。无意中我发现了,在 UINavigationController 根视图上进行右滑返回上级页面时,页面就会卡死。原因找到了,一定是手势冲突。
问题原因描述
在我的项目中有一个基类 BaseViewController
,由于项目中有时候需要隐藏 NavigationBar
所以我使用了 setNavigationBarHidden()
方法,使用这个方法会导致右滑返回上级页面的操作失效。所以我在 BaseViewController
中加入了如下的代码:
1 | self.navigationController?.interactivePopGestureRecognizer?.delegate = self |
我没有实现任何 UIGestureRecognizerDelegate
的方法,也就是用的都是默认情况。右滑时,具体的操作是将导航栏堆栈最顶部的 Controller
进行 pop
操作,但是当栈顶没有 Controller
时,也就是 Controller
为 rootViewController
时,这时候去开启右滑就会出问题了。导致页面完全卡死。
Swift 下使用 SQLite 教程:入门【译】
更新说明:本教程已由 Nikolas Burk 更新为 Xcode 9,iOS 11 和 Swift 4。最初的教程由 Chris Wagner 编写。
这篇教程向你展示了如何在 Swift 平台上使用流行的数据库 SQLite。在软件开发的领域,你需要很长时间才能保存应用数据。在很多情况下,这是以数据结构形式出现的。但是,如何有效的存储它 – 什么是有效的存储?
幸运的是,一些伟大的思想家已经开发出用于在数据库中存储结构化数据和编写语言功能以访问数据的解决方案。SQLite 默认在 iOS 中是可用的。实际上,如果你以前使用过 Core Data,那么你实际上已经使用过 SQLite,因为 Core Data 只是 SQLite 上的一个层封装,它提供了更方便的API。
通过这篇教程,你将学习到如何执行以下数据库的操作:
- 创建和连接一个数据库
- 创建一个表
- 插入一行
- 更新一行
- 删除一行
- 查询数据库
- 处理 SQLite 错误
在学习如何执行这些基本操作之后,你将看到如何以类似 Swift 的方式将它们包装起来。这将允许你为应用程序编写抽象 API,以便你(大多数)可以避免去直接使用 SQLite 的 C API 的痛苦!:]
最后,我将简要介绍一下流行的开源 Swift 包装器 SQLite.swift,以便你能大致的了解一下底层框架是如何工作的。
注意:数据库,甚至只是 SQLite 本身,都是一个非常大的主题,因此它们大多超出了本教程的范围。本教程假设你对关系数据库意识形态有基本的了解,并且你主要在这里学习如何在 Swift 下使用 SQLite。
Swift 面向协议 - 为类提供基于 Storyboard 的初始化方法
之前我们说过了运用面向协议的思想为控件添加 action
今天我们再来写一个基于 Storyboard
的初始化方法。在我的项目中,我没有将所有的 controller
都放在一个 Storyboard
文件中,原因有两个:
- 当
Controller
很多的时候不方便查找对应的Storyboard
。 - 打开
Storyboard
会非常卡。
所以我将 Controller
拆分成一个个的 Storyboard
文件。在对应的类中,我需要在每个类都写上一个初始化方法:
1 | static func instantiate() -> HomeViewController { |
WKWebView 中注入 cookie
在项目中,往往有这样的要求,用 API 进行登录之后在某个 WKWebView
的页面需要用 cookie
去验证身份(虽然我更喜欢用 accesstoken
去验证🙃)。WKWebView
是苹果官方建议的控件来替代老旧的 UIWebView
。但是 WKWebView
的 cookie
无法共享 NSHTTPCookieStorage
,所以这时候就需要我们自己去管理 cookie
。(iOS 11 上新增了 WKHTTPCookieStore
来管理)
首先我们先解析获取到的 cookie
1 | /// 解析 cookie |
处理 initialize() 的弃用【译】
在将项目迁移到 Swift 3.1 后,我受到了几个警告的欢迎。它们似乎都没有特别难以修复,只是除了这个之外:
Method ‘initialize()’ defines Objective-C class method ‘initialize’, which is not guaranteed to be invoked by Swift and will be disallowed in future versions.
Ouch。一些类重写了 NSObject
的 initialize()
函数,警告清楚地表明这已不在合适(或者至少,但它应该不会很快发生)。一个非常类似的方法 - load()
,它自 Swift 1.2 以来一直没有,所以看起来初始化将很快跟进。它扮演着一个独特的角色,如 NSObject
文档所述:
The runtime sends
initialize()
to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program.
iOS 11 中 UIRefreshControll 消失【译】
在 Swift 4 中 NavigationBar 不同颜色时的转场
我们在项目中,往往会遇到两个 Navigation Bar 样式不同的问题,如果直接用苹果官方的控件,会出现各种各样的 bug,因为苹果官方的 Navigation Bar 是共用的,所以在两个不同样式的 Navigation Bar 中做转场操作的时候就会出现各种问题。
今天我们就用 Method Swizzling 的方式来修改一下系统的 Navigation Bar 转场时的样式,最终效果如下图所示:
设置导航栏的背景颜色
我们来为 UIViewController
添加一个扩展,用于存储与设置 Navigation Bar
各种属性。首先,我们来为我们的 UIViewController
添加一个 navBarBgColor
的计算属性。
这里运用了 runtime
的关联方法 objc_getAssociatedObject:
和 objc_setAssociatedObject:
来存取所设置的背景颜色。
1 | extension UIViewController { |
iOS 配置测试用推送通知证书
最近做通知的时候需要对通知进行测试,之前没有做证书的经验,这次尝试了一下,写这篇文章备忘。
测试用的工具叫做 Pusher,下载地址:NWPusher。非常的好用。
创建测试用 Push 证书
1、打开苹果开发者页面:Developer,登录账户。
2、在账户的 Certificates, Identifiers & Profiles
页面找到 Identifiters
,选择 App IDs
。
3、找到自己 App,点击打开,能看到如下所示。
如果你没有配置 Push Notifications
,那么它的 Development
和 Distribution
都是 Configurable
状态。点击 Edit
按钮。
我们要创建测试用的证书就点击 Development SSL Certificate
下面的 Create Certificate
。