tripleCC的技术博客

ʕ•̫͡•ʔ-̫͡-ʕ•͓͡•ʔ-̫͡-ʕ•̫͡•ʔ-̫͡-ʕ•͓͡•ʔ-̫͡-ʔ

关于keychain封装库Locksmith

Locksmith是一个面向协议编程的keychain封装库,也是我见过的对面向协议贯彻最彻底的一个第三方库。

Locksmith基本实现

iOS系统中有5种keychain类型:generic passwords, internet passwords, certificates, keys,以及 identities。并且针对每个类型都有4种操作:create, read, update,以及 delete。

对于以上复杂的逻辑关系,Cocoa采用了一系列字符串常量以及对应的key/value进行操作。只是对于Swift来说,这种方式过于冗余而且难以记忆,并没有充分利用到其语言特性。

Locksmith作者采用了protocol来解决原生方案过于复杂的问题。就像乐高玩具一样,可以随意组装不同的组件来达到不同的视觉效果,Locksmith可以让使用者遵守特定的protocol来获取对应的功能,比如需要delete功能,那么就遵循DeleteableSecureStorable协议;需要read功能,那么就遵守ReadableSecureStorable协议。而在对应的模型中,不需要额外添加函数,协议内部通过extension已经实现了对应的功能函数。开发者直接调用deleteFromKeychain或者readFromKeychain即可实现想要的功能。

iOS知识碎片四

1、显示CoreData执行的SQL语句
2、监听UITextView键盘的发送按钮
3、设置CoreData实体唯一约束
4、iOS9关于canOpenURL不生效
5、OC变参函数

在Ubuntu下编译Swift

哎,近半年没有在Ubuntu的字符终端下畅爽地码代码了(那种Ctrl+Alt+F1~F6然后只有不同颜色的字符在屏幕上跳跃的感觉现在想起来还是超爽啊!),今天恰好来试下在Ubuntu下编译Swift,因为要截图,所以只能在图形界面的虚拟终端下码了- -。

下载工具包

首先需要进这这里下载对应的工具包,因为我的系统是去年安装的Ubuntu14.04所以选择最后一个。

解压工具包

然后进入下载文件夹解压:

可以看到解压后,目录下有下面几个子目录:

主要说明三个子目录

1
2
3
bin   可执行文件
lib   可执行文件动态库
share man

Swift2.0中的case匹配

Swift在2.0版本之后,对if、guard、for的匹配进行了一定的加强,其中case匹配模式感觉还是挺新奇的。

参照Swift官方手册,可以知道,这种模式在针对可选值进行处理时,可以获得额外的便利:

1
2
3
4
5
6
7
8
9
10
let someOptional: Int? = 42
// Match using an enumeration case pattern
if case .Some(let x) = someOptional {
    print(x)
}

// Match using an optional pattern
if case let x? = someOptional {
    print(x)
}

x?是.Some(let x)的简写方式。单从以上代码段,可能还看不出有什么特别之处,相反还比以前的实现繁琐:

1
2
3
if let x = someOptional {
    print(x)
}

不过官方手册体现其便利的是for关键字,if还需要另一种场景来体现其带来的便利:

1
2
3
4
5
6
7
8
9
10
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// Match only non-nil values
for case let number? in arrayOfOptionalInts {
    print("Found a \(number)")
}

// 输出
// Found a 2
// Found a 3
// Found a 5

可以看到,在遍历可选值数组的场景下,这种方式确实减少了一些代码,要是以前,我可能会这样实现:

在Swift实现Struct归档

1
2
3
4
struct AboutMe {
    var detail: String
    var links: [[String : String]]
}

在Swift中,Struct类型是无法进行归档操作的,只有继承自NSObject并且遵守了NSCoding协议的类才可以进行相应的归档操作。也就是将上面结构体改成类:

1
2
3
4
5
6
7
8
9
10
11
12
class AboutMe: NSObject, NSCoding {
    var detail: String
    var links: [[String : String]]
    required init?(coder aDecoder: NSCoder) {
        aDecoder.decodeObjectForKey("detail")
        aDecoder.decodeObjectForKey("links")
    }
    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(detail)
        aCoder.encodeObject(links)
    }
}

但是如果要对Struct进行归档,可以转换思维,使用按照以下步骤实现。

Xcode快捷键

  • command + shift + o 快速定位文件
  • command + shift + y 隐藏下方debug框
  • command + shift + c 聚焦下方debug框
  • command + option + 0 右方工具框
  • command + 0 左方工具框
  • command + option + [ 代码上调
  • command + [ 代码左调
  • shift + commad + j 将文件目录切换到打开的文件
  • control + 1 选中要查看的方法名,按下快捷键后,点击celler,可以查看哪些方法调用了此方法
  • esc 枚举显示自动补全
  • command + d storyboard中复制拷贝控件
  • option + shift 可以移动仿真器中的手指
  • control + i = control + [ 代码对齐
  • option + 单击文件 文件显示在辅助窗口
  • control + shift + 左击 显示IB中所有控件
  • command + shift + option + 左/右 隐藏/显示方法内容

Swift源码阅读Runtime

Swift开源之后,虽然大部分代码对于作为应用程序猿的我来说,花费大量时间去阅读,性价比有点不高,但是阅读下Foundation,学习学习Swift的编码范式还是不错的。

NSEnumerator.swift
1.遵循多个约束

其中范型NSGeneratorEnumerator定义如下:

1
2
3
4
5
6
7
8
9
10
internal class NSGeneratorEnumerator<Base : GeneratorType where Base.Element : AnyObject> : NSEnumerator {
    var generator : Base
    init(_ generator: Base) {
        self.generator = generator
    }

    override func nextObject() -> AnyObject? {
        return generator.next()
    }
}

上面有一点,就是范型类型的约束:遵守协议GeneratorType,并且是AnyObject类型。这个上次写的时候忘了,刚好这次记下这种写法。

iOS知识碎片三

1、NSSetUncaughtExceptionHandler注册捕获错误无法调用
2、自定义提示宏
3、frame和bounds
4、Swift中inout和C/C++中指针/引用的区别
5、获取UICollectionView的高度

Git开发流程

使用Git开发总结

现在很多互联网公司都是通过分布式的Git进行代码管理,SVN则逐渐被淘汰了。以下就是自己在Git开发中的流程与注意点:
1、所有人fork一份 project, 在自己的repository上开发,开发完成后向 project 提 pull request.

2、如果遇到需要多人共同开发的比较大的项目,可以细分为个人完成的小项目,在各自 repository 上完成后 pull request.

3、尽量保持每天至少 pull request 一次。如果功能一天不能完成,则每天抓取 project最新的版本 merge 并解决冲突,保证每次最终 pull request 的冲突减到最少。

4、尽量保证提交前能看一遍每行改动 (如果使用 SourceTree, 可以看到对于每一行的改动,并选择是否提交/回滚这行的改动),确保每行都是必要的。

5、另外,iOS 项目中有一些 .gitignore 也无法忽略的文件,比如 project.pbxproj 和 *.xcodecheckout,需要每次手动来忽略其中的改动,务必确保这些文件内所有改动的行都是必要的,除非特殊情况不要提交其中的 PROVISIONING_PROFILE 和 Build Settings 相关的改动。