使用 Let's Encrypt 通配符证书

一直在使用 Let’s Encrypt 的免费 SSL 证书,但是一直没做笔记。今天看到 Let’s Encrypt 支持了通配符证书(Wildcard Certificates),也就是说二级子域名和主域名可以共用一个证书。 申请证书 # 下载证书申请客户端 cd /opt git clone https://github.com/certbot/certbot cd /opt/certbot # 注意通配符并不包含主域名,所以要配置两个 ./certbot-auto certonly -d *.zyf.im -d zyf.im --manual --preferred-challenges dns --server "https://acme-v02.api.letsencrypt.org/directory" -preferred-challenges dns 使用 DNS 方式校验域名所有权,所以会遇到: ------------------------------------------------------------------------------- Please deploy a DNS TXT record under the name _acme-challenge.zyf.im with the following value: YZ2unEViXH8nYZ2unEViIbW52LhIEViIbW52Lh Before continuing, verify the record is deployed. ------------------------------------------------------------------------------- Press Enter to Continue 要在域名服务商那里将 _acme-challenge.zyf.im 配置 DNS TXT 记录,从而校验域名所有权。 ...

April 26, 2018 · 2 min · 227 words · Me

Docker UFW 失效

今日遇到 Docker 中的项目绕过了宿主机 UFW 的配置,可以被任意 IP 访问,甚是奇怪。查找资料发现: 如果你在 Linux 使用 Docker,很可能你的系统防火墙降级为 Uncomplicated Firewall (UFW)。如果是这样的话,你有一点可能不知道,Docker 和 UFW 的组合带来了一些安全问题。为什么呢?因为 Docker 实际上绕过了 UFW 并直接修改了 iptables,所以一个容器可以绑定一个端口。这就意味着,所有你设置的 UFW 规则都将在 Docker 容器中失效。 如何修复: sudo vi /etc/default/docker # add the following line: DOCKER_OPTS="--iptables=false" Restart the docker daemon: sudo systemctl restart docker # or docker/etc/init.d/docker restart When a problem arises, it only takes a bit of digging to discover the solution was already there, waiting for you to make it so. Don’t let this issue with Docker stop you from using this incredible technology. ...

April 24, 2018 · 1 min · 119 words · Me

Swift 初始化

因为自己是直接从 Swift 进入的 iOS 开发,Swift 与 Objective-C 初始化的对比就不多提了。感觉上 Swift 初始化的方式像 Java,自己也只这样套着 Java 去理解,但也发现了不相同的地方。 初始化顺序 class Blog: NSObject { let param: String override init() { } } 这里有条错误 error: property 'self.param' not initialized at implicitly generated super.init call 说明:param 参数没有在隐式生成 super.init 调用之前完成初始化。 Swift 中并不是不调用 super.init 而是为了方便开发者由编译器完成了这一步,但是要求调用 super.init 之前要完成成员变量的初始化。 class Blog: NSObject { let param: String override init() { param = "swift init" } } 对于需要修改父类中成员变量值,我们需要在调用 super.init 之后再进行修改: class Cat { var name: String init() { name = "cat" } } class Tiger: Cat { let power: Int override init() { power = 10 super.init() name = "tiger" } } Swift 中类的初始化顺序: ...

March 31, 2018 · 5 min · 972 words · Me

iOS Safe Area 我所知道的全部

在 iOS 7 Apple 在 UIViewController 中引入了 topLayoutGuide 和 bottomLayoutGuide 属性来描述没有被覆盖(status bar, navigation bar, toolbar, tab bar, etc.)屏幕的区域。在 iOS 11 中,Apple 已经弃用了这些属性,并引入了 safe area。Apple 建议我们不要在 safe area 操作,在 iOS 11 中,当在 iOS App 中定位视图时,你必须使用新的 safe area API。 UIView 在 iOS 11 UIViewController topLayoutGuide 和 bottomLayoutGuide 属性已经被替换成了新的 UIView 中的 safe area: @available(iOS 11.0, *) open var safeAreaInsets: UIEdgeInsets { get } @available(iOS 11.0, *) open var safeAreaLayoutGuide: UILayoutGuide { get } safeAreaInsets 属性意味着屏幕可以覆盖从四个方向,而不仅仅是顶部和底部。当被 iPhone X 呈现时,我们就明白了为什么我们需要左右 insets。 iPhone 8 vs iPhone X safe area (portrait orientation) ...

March 29, 2018 · 5 min · 965 words · Me

UITableViewCell 自适应 UITextView 高度

使用 Auto Layout 让 UITableViewCell 自适应 UITextView 高度,效果演示: 99-projects-of-swift/029-tableviewcell-self-adaption 预备步骤 给 textView 上下左右建立相对于 cell 的约束 取消 textView 的 Scrolling Enabled 设置 tableView 估算高度 tableView.estimatedRowHeight = 70 设置 textView.delegate = self 关键点 如果在 textViewDidChange(textView:) 调用 tableView.reloadData() 会造成 textView 失去焦点,键盘隐藏。 解决方法: func textViewDidChange(textView: UITextView) { tableView.beginUpdates() tableView.endUpdates() } 这里带来了一个问题,当 textView 长度超过一屏或者过长时,在输入时 tableView 会跳动滚动 jumping and stuttering。 更好的解决方法: func textViewDidChange(textView: UITextView) { let currentOffset = tableView.contentOffset UIView.setAnimationsEnabled(false) tableView.beginUpdates() tableView.endUpdates() UIView.setAnimationsEnabled(true) tableView.setContentOffset(currentOffset, animated: false) } 禁用动画和重建表视图的内容偏移修正抖动。 ...

March 27, 2018 · 1 min · 87 words · Me

【译】iOS 单元测试和 UI 测试入门教程

iOS Unit Testing and UI Testing Tutorial 编写测试并不迷人 (glamorous),但是既然测试能让你闪闪发光 (sparkling) 的应用程序避免变成 (from turning into) 一堆乱七八糟的垃圾,那么说明测试是必要的。如果你正在阅读这篇教程,那么你已经知道你 应该 为代码和 UI 编写测试,但是你可能不知道如何做。 也许你已经有一个 “可以运行” 的应用,但想测试你正在进行的扩展应用的更改。也许你已经编写了一些测试,但不确定它们是否是 正确 的测试。或者,你已经开始开发一个新应用,想要边开发边测试。 这篇教程将告诉你如何: 使用 Xcode 的测试导航器来测试应用的模型和异步方法 通过使用存根 (stubs) 和模拟对象 (mocks) 模拟与库或系统对象的交互 测试 UI 和性能 使用代码覆盖率工具 在此过程中,你将学到一些测试高手常用的专业术语。 开始 首先,下载教程素材。它包含一个基于 UIKit Apprentice 中的示例应用的 BullsEye 项目。这是一个简单的运气和机会游戏。游戏逻辑在 BullsEyeGame 类中,你将在本教程中对其进行测试。 测试什么 在编写任何测试之前,重要的是了解基础知识。你需要测试什么? 如果你的目标是扩展现有应用,你应该首先为计划更改的任何组件编写测试。 一般来说,测试应该覆盖: 核心功能:模型类和方法及其与控制器的交互 最常见的 UI 工作流 边界条件 Bug 修复 测试的最佳实践 首字母缩写 FIRST 描述了有效单元测试的一套简明标准。这些标准是: Fast:测试应该快速运行。 Independent/Isolated:测试之间不应共享状态。 Repeatable:每次运行测试时,都应获得相同的结果。外部数据提供者或并发问题可能导致间歇性失败。 Self-validating:测试应完全自动化。输出应该是"通过"或"失败",而不是依赖程序员对日志文件的解释。 Timely:理想情况下,你应该在编写生产代码之前编写测试它们的测试。这被称为测试驱动开发。 遵循 FIRST 原则将使你的测试保持清晰有用,而不会成为应用开发的障碍。 ...

March 15, 2018 · 4 min · 680 words · Me

【Git 权威指南】读书笔记 - 协同模型

主要内容:【Git 协同模型】 经典 Git 协同模型 集中式协同模型 可以像集中式版本控制系统那样使用 Git,在一个大家都可以访问到的服务器上架设 Git 服务器,每个人从该服务器克隆代码,本地提交推送到服务器上。 金字塔式协同模型 虽然理论上每个开发者的版本库都是平等的,但是会有一个公认的权威的版本库,这个版本库由一个或者多个核心开发者负责维护(具有推送的权限)。 开源社区逐渐发展出金字塔模型,而这也是必然之选。 Topgit 协同模型 笔者注:Topgit 是否已经过时? 卖主分支 Vendor Branch 是在版本库中专门创建一个和上游同步的分支,一旦有上游代码发布就捡入到卖主分支中。 子模组协同模型 创建子模组 git submodule add /path/to/repos/libA.git lib/lib_a .gitmodules 的内容: cat .gitmodules [submodule "lib/lib_a"] path = lib/lib_a url = /path/to/repos/libA.git 克隆带子模组的版本库 git clone /path/to/repos/super.git /path/to/my/workspace/super-clone 子模组的版本库并不会默认克隆,如果需要克隆出子模组型式引用的外部库,需要执行: git submodule init git submodule update 在子模组中修改和子模组的更新 修改更新的方式和普通仓库一样。如果修改了子模块,要先推送子模块的修改,再推送主仓库,以防止其他人克隆 super 版本库、更新模组时因为找不到该子模组版本库相应的提交而导致出错。 查看子模组状态: git submodule status 子树合并 引入外部版本库 # 注册外部版本库 git remote add util /path/to/repos/util.git git fetch util # 查看所有分支 git branch -a # 从 util/master 远程分支创建一个本地分支 util-branch git checkout -b util-branch util/master 子目录方式合并外部版本库 # 在主分支,将分支 util-branch 读取到当前分支的一个子目录下 git read-tree --prefix=lib util-branch # 将 lib 目录下的文件更新出来 git checkout -- lib 现在还不能忙着提交,因为如果现在进行提交就体现不出来两个分支的合并关系。需要使用 Git 底层的命令进行数据提交。 ...

January 19, 2018 · 2 min · 339 words · Me

【Git 权威指南】读书笔记 - 和声

主要内容:【Git 协议与工作协同】、【冲突解决】、【Git 里程碑】、【Git 分支】、【远程版本库】、【补丁文件交互】 Git 协议与工作协同 Git 支持的协议 SSH、GIT、HTTP、HTTPS、FTP、FTPS、RSYNC 及前面已经看到的本地协议。 SSH 协议: ssh://[user@]example.com[:port]/path/to/repo.git/ [user@]example.com:path/to/repo.git/ GIT 协议,最常用的只读协议: git://example.com[:port]/path/to/repo.git/ HTTP[S] 协议: http[s]://example.com[:port]/path/to/repo.git/ 强制非快进式推送 git push -f 强制推送,会强制刷新服务器中的版本。 禁止非快进式推送 git --git-dir=/path/to/repos/shared.git config receive.denyNonFastForwards true 冲突解决 拉回操作中的合并 git pull = git fetch + git merge 合并策略 Merge Strategis Git 合并操作支持很多合并策略,默认会选择最适合的合并策略。例如,和一个分支进行合并时会选择 recursive 合并策略,当和两个或两个以上的其他分支进行合并时采用 octopus 合并策略。 git merge [-s <strategy>] [-X <strategy-option>] [<commit>...] This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. git merge -s recursive -X ours [<commit>...] Merge branch obsolete into the current branch, using ours merge strategy: ...

January 17, 2018 · 3 min · 469 words · Me

R.swift 强类型引用资源文件

R.swift 获取强类型、自动编译的图片、字体、segues 等资源。 以避免无法编译时检查 字符串 的形式引用资源所导致的错误。 let icon = UIImage(named: "settings-icon") let font = UIFont(name: "San Francisco", size: 42) let color = UIColor(named: "indictator highlight") let viewController = CustomViewController(nibName: "CustomView", bundle: nil) let string = String(format: NSLocalizedString("welcome.withName", comment: ""), locale: NSLocale.current, "Arthur Dent") With R.swift let icon = R.image.settingsIcon() let font = R.font.sanFrancisco(size: 42) let color = R.color.indicatorHighlight() let viewController = CustomViewController(nib: R.nib.customView.name) let string = R.string.localizable.welcomeWithName("Arthur Dent") 配置 其中 GitHub 上有的就不再累述了,主要注意: 添加 R.generated.swift 不要勾选 Copy items if needed,软引用就好。 要在 .gitignore 添加 *.generated.swift 以避免不必要的冲突。 添加新的资源文件后需要 command + b 编译下,才可以使用。 .clr 颜色文件的创建和使用 使用 Xcode 创建 .clr 文件: 之后可以在其中添加颜色,选择颜色回车可以对颜色从新命名。 生成的 .clr 文件保存在 ~/library/Colors 下,可以导入到项目后再通过 R.color 使用。 Tips 打开、关闭隐藏文件: command + shift + . References XCode Tip: Color Palette

January 17, 2018 · 1 min · 116 words · Me

Xcode 不知名的实用技巧

状态栏 Help Search 框可以很方便的检索到相关的设置项。 Navigator ⌘ 1 .. ⌘ 7 可以切换窗口。 Show the Symbol navigator 在类不多时,可以方便看所有类的结构,类多时时使用下面的 filter 功能。 Show the Breakpoint navigator 点击右下角 + 选择 Exception Breakpoint..,可以在添加更明确的报错点,可以选择语言是 obj-c 还是 Swfit。 Utilities ⌘ ⌥ 1 .. ⌘ ⌥ 7 可以切换窗口。 Show the Code Snippet Library 代码片段模板,也可以将自己的写好的片段拖入。 Show the Media Library 可以直接从中拖拽图片成 UIImageView 放入 xib 中。 ...

January 12, 2018 · 1 min · 159 words · Me