作为一名软件工程师,好处之一就是如果我们对手上的工具不甚满意的话,我们可以自行对这个工具进行完善。Swift 让这个优化过程变得更为轻松,它提供了许多特性从而允许我们能够自然而然地扩展和自定义这门语言。
在本篇文章中,我打算为大家分享一系列 Swift 小贴士,以表述 Swift 是如何让我的生活更加美好的。我希望本文能够抛砖引玉,让您对这门语言有更深甚至更好的想法,并付诸行动(切记要三思而后行!)。
干掉重复的标识符
您可能已经熟悉了 Objective-C 中的一个使用惯例:那就是枚举值以及其字符常量通常都有长得吓人的描述名:
1 |
label.textAlignment = NSTextAlignmentCenter; |
(这让我想起了从中学课上学习到的一条准则:在答案中要复述问题,简称 RQIA。问:在这个例子中是哪一个文本对齐方式呢?答:在这个例子中是居中文本对齐方式。这对老师批阅试卷来说是非常有效的一种做法,因为老师很可能记不住问题,但是在其他情况下这种做法会显得十分繁杂。)
Swift 减少了冗余度,因为枚举值可以在类型名之后加上点语法进行访问,即使你省略掉了类型姓名它仍然能够推断出来:
1 2 3 4 |
label.textAlignment = NSTextAlignment.Center // 更为简洁: label.textAlignment = .Center |
然而,很多时候我们很可能不会用到枚举,遇上的往往是这样很长很长的一个构造器:
1 |
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) |
代码中会有多少个“timingFunction”?很可能多到无法想象。
有一个不为人知的小技巧,就是缩略形式的点语法对于所有类型的静态成员来说都是有效的。通过在扩展中增加自定义的属性就可以应用上这个技巧了……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
extension CAMediaTimingFunction { // 这个属性是懒加载属性,第一次被访问时才会被初始化。 // (@nonobjc 标记是必须的,这可以阻止编译器试图为一个 // 静态属性创建动态访问器(也就是令其不可继承)。 @nonobjc static let EaseInEaseOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) // 另一个方法就是使用计算性属性,这也同样有效, // 但是*每次*访问它的时候都将重新计算,可能带来性能问题: static var EaseInEaseOut: CAMediaTimingFunction { // .init is short for self.init return .init(name: kCAMediaTimingFunctionEaseInEaseOut) } } |
这样我们就可以很方便地简化这个操作了:
1 |
animation.timingFunction = .EaseInEaseOut |
上下文环境
处理 Core Graphics 上下文、色区之类的代码同样也会非常非常长:
1 2 |
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), CGColorCreate(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), [0.792, 0.792, 0.816, 1])) |
我们仍然使用万能的扩展:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
extension CGContext { static func currentContext() -> CGContext? { return UIGraphicsGetCurrentContext() } } extension CGColorSpace { static let GenericRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) } CGContextSetFillColorWithColor(.currentContext(), CGColorCreate(.GenericRGB, [0.792, 0.792, 0.816, 1])) |
看起来要简单不少。当然,还有很多方法可以扩展 Core Graphics,从而让它符合您的需求。
自动布局
这是不是似曾相识?