轩辕十四

探索科技与创新的个人博客

今天在做在线预览功能的时候碰到了一个蛋疼的问题,office 格式都可以完美的适配,但是 txt 格式出现了乱码。没办法只能进行一个转码,然后再输出内容。

提取 TXT 文件内容并转码 utf8


1
2
3
4
5
do {
var encoding: String.Encoding = .utf8
let body = try String(contentsOf: url, usedEncoding: &encoding)
return body
} catch {}

这里我们的 body 就是我们获取的内容,默认的我们用了 utf8 编码格式,如果转码错误,说明文件的编码格式为其他格式。

阅读全文 »

跨线程订阅的问题似乎在 RxSwift Slack 上一次又一次的被提到。这个解释起来也是非常的简单所以我觉得放在博客当中是一个好主意,无论你在何时需要,都可以通过连接进行访问,我也不用一次又一次的回复。

可观察序列的订阅(Observable subscriptions)


subscribing(订阅) 和 observing(观察) 方面的术语还有一点混乱,所以让我们先来解决这个问题(不要跳过本章节!)。

让我们看看 observable subscription 的工作原理。我们可以将订阅分成 3 个部分:

阅读全文 »

最近在做的一款 App 测试中出现了一个非常诡异的问题,偶尔的界面卡死,但是又并不是 Crash,没有抛出任何异常,把 App 切到后台然后在点开又恢复了,只不过转场的时候十分诡异,似乎完全没有动画,转场背景还是黑的。

什么原因呢?死循环?不可能;内存泄漏?也不可能?😂;手势冲突?很有可能🧐。无意中我发现了,在 UINavigationController 根视图上进行右滑返回上级页面时,页面就会卡死。原因找到了,一定是手势冲突。

问题原因描述


在我的项目中有一个基类 BaseViewController,由于项目中有时候需要隐藏 NavigationBar 所以我使用了 setNavigationBarHidden() 方法,使用这个方法会导致右滑返回上级页面的操作失效。所以我在 BaseViewController 中加入了如下的代码:

1
2
3
4
self.navigationController?.interactivePopGestureRecognizer?.delegate = self

extension BaseViewController: UIGestureRecognizerDelegate {
}

我没有实现任何 UIGestureRecognizerDelegate 的方法,也就是用的都是默认情况。右滑时,具体的操作是将导航栏堆栈最顶部的 Controller 进行 pop 操作,但是当栈顶没有 Controller 时,也就是 ControllerrootViewController 时,这时候去开启右滑就会出问题了。导致页面完全卡死。

阅读全文 »

更新说明:本教程已由 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。

阅读全文 »

之前我们说过了运用面向协议的思想为控件添加 action 今天我们再来写一个基于 Storyboard 的初始化方法。在我的项目中,我没有将所有的 controller 都放在一个 Storyboard 文件中,原因有两个:

  • Controller 很多的时候不方便查找对应的 Storyboard
  • 打开 Storyboard 会非常卡。

所以我将 Controller 拆分成一个个的 Storyboard 文件。在对应的类中,我需要在每个类都写上一个初始化方法:

1
2
3
4
static func instantiate() -> HomeViewController {
return UIStoryboard(name: .home)
.instantiateViewControllerWithClass(type: HomeViewController.self)
}
阅读全文 »

在项目中,往往有这样的要求,用 API 进行登录之后在某个 WKWebView 的页面需要用 cookie 去验证身份(虽然我更喜欢用 accesstoken 去验证🙃)。WKWebView 是苹果官方建议的控件来替代老旧的 UIWebView。但是 WKWebViewcookie 无法共享 NSHTTPCookieStorage,所以这时候就需要我们自己去管理 cookie。(iOS 11 上新增了 WKHTTPCookieStore 来管理)

首先我们先解析获取到的 cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// 解析 cookie
private func analysisCookie(response: HTTPURLResponse) {

if let fields = response.allHeaderFields as? [String: String],
let url = response.url
{
let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields,
for: url)
let storage = HTTPCookieStorage.shared
for cookie in cookies {
/// 将 cookie 存入本地
storage.setCookie(cookie)
}
}
}
阅读全文 »

在将项目迁移到 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。一些类重写了 NSObjectinitialize() 函数,警告清楚地表明这已不在合适(或者至少,但它应该不会很快发生)。一个非常类似的方法 - 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.

阅读全文 »


我有一个带有 largeTitlesearchcontrollernavigationBar ,我的 tableView 有一个 refreshcontrol

当我拉动刷新时,refreshcontrolactivityIndicator 消失了,但是刷新过程仍然在继续,即使进程完成并且我调用 UIRefreshControllendRefreshing() 方法,导航栏也不会恢复到正常大小。

有人遇到过同样的问题吗?

阅读全文 »

我们在项目中,往往会遇到两个 Navigation Bar 样式不同的问题,如果直接用苹果官方的控件,会出现各种各样的 bug,因为苹果官方的 Navigation Bar 是共用的,所以在两个不同样式的 Navigation Bar 中做转场操作的时候就会出现各种问题。

今天我们就用 Method Swizzling 的方式来修改一下系统的 Navigation Bar 转场时的样式,最终效果如下图所示:

设置导航栏的背景颜色


我们来为 UIViewController 添加一个扩展,用于存储与设置 Navigation Bar 各种属性。首先,我们来为我们的 UIViewController 添加一个 navBarBgColor 的计算属性。
这里运用了 runtime 的关联方法 objc_getAssociatedObject:objc_setAssociatedObject: 来存取所设置的背景颜色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extension UIViewController {
/// 设置导航栏的背景颜色
public var navBarBgColor: UIColor {
get {
if let color = objc_getAssociatedObject(self, &DefaultValue.navBarBgColor) as? UIColor {
return color
}
return DefaultValue.navBarBgColor
}
set {
objc_setAssociatedObject(self, &DefaultValue.navBarBgColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
navigationController?.navBarBackgroundColor(newValue)
}
}
}
阅读全文 »

最近做通知的时候需要对通知进行测试,之前没有做证书的经验,这次尝试了一下,写这篇文章备忘。

测试用的工具叫做 Pusher,下载地址:NWPusher。非常的好用。

创建测试用 Push 证书


1、打开苹果开发者页面:Developer,登录账户。

2、在账户的 Certificates, Identifiers & Profiles 页面找到 Identifiters,选择 App IDs

3、找到自己 App,点击打开,能看到如下所示。

如果你没有配置 Push Notifications,那么它的 DevelopmentDistribution 都是 Configurable 状态。点击 Edit 按钮。

我们要创建测试用的证书就点击 Development SSL Certificate 下面的 Create Certificate

阅读全文 »
0%