由于现在手头上的项目是基于frame开发的,没有xib或者storyboard,没有使用自动布局,所以排布界面时总是显得很繁琐。
令人蛋疼的frame布局
老代码对界面的坐标尺寸设置都是通过下面的方式:
1 | ... |
这些坐标设置工作都是在初始化,也就是init系列方法中完成的。这样做的弊端很明显,复用性很差,如果还是按照这种方式的话,每扩展一种界面类型,就要新增一个init方法。久而久之,冗余代码会越来越多,新增特性想重用这块控件的话,需要做比较多的无用功。
由于现在手头上的项目是基于frame开发的,没有xib或者storyboard,没有使用自动布局,所以排布界面时总是显得很繁琐。
老代码对界面的坐标尺寸设置都是通过下面的方式:
1 | ... |
这些坐标设置工作都是在初始化,也就是init系列方法中完成的。这样做的弊端很明显,复用性很差,如果还是按照这种方式的话,每扩展一种界面类型,就要新增一个init方法。久而久之,冗余代码会越来越多,新增特性想重用这块控件的话,需要做比较多的无用功。
昨天产品在teambition上提了一个bug:点击特定的页面app闪退。
我很是纳闷,因为通过其它类型索引进入的详情页面都不会出现这样的情况,为什么偏偏是这个页面?还是因为memory warning而闪退?而且内存不是慢慢增加,而是从80M左右激增到600M+
接着我查看了进入这个页面时获取的json,仔细观察后,发现并没有特别的地方。于是我决定使用instruments的Allocations查看到底是什么操作占用了如此庞大的内存。
进入界面之后,展示的界面如下图:
Locksmith是一个面向协议编程的keychain封装库,也是我见过的对面向协议贯彻最彻底的一个第三方库。
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即可实现想要的功能。
Swift在2.0版本之后,对if、guard、for的匹配进行了一定的加强,其中case匹配模式感觉还是挺新奇的。
参照Swift官方手册,可以知道,这种模式在针对可选值进行处理时,可以获得额外的便利:
1 | let someOptional: Int? = 42 |
x?是.Some(let x)的简写方式。单从以上代码段,可能还看不出有什么特别之处,相反还比以前的实现繁琐:
1 | if let x = someOptional { |
不过官方手册体现其便利的是for关键字,if还需要另一种场景来体现其带来的便利:
1 | let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5] |
可以看到,在遍历可选值数组的场景下,这种方式确实减少了一些代码,要是以前,我可能会这样实现:
1 | struct AboutMe { |
在Swift中,Struct类型是无法进行归档操作的,只有继承自NSObject并且遵守了NSCoding协议的类才可以进行相应的归档操作。也就是将上面结构体改成类:
1 | class AboutMe: NSObject, NSCoding { |
但是如果要对Struct进行归档,可以转换思维,使用按照以下步骤实现。