作者:Ole Begemann,原文链接,原文日期:2016-10-13
译者:Cwift;校对:walkingway;定稿:CMB

我在前面的文章中提到过,Swift 中有两个基础的区间(Range)类型:RangeClosedRange,并且这两个类型不能互相转换。这使得编写一个同时适用于两种区间类型的函数变得很困难。

昨天,swift-users 的邮件列表中有人问了一个具体的问题:假设你写了一个名为 random 的函数,它接受一个整数的区间,并返回一个该范围中的随机值:

import Darwin //在 Linux 上也可以用 Glibc

func random(from range: Range<Int>) -> Int {
let distance = range.upperBound - range.lowerBound
let rnd = arc4random_uniform(UInt32(distance))
return range.lowerBound + Int(rnd)
}

你可以使用一个半开的区间调用这个函数:

let random1 = random(from: 1..<10)

但是你不能传入一个闭合的区间:

let random2 = random(from: 1...9) // error

太差劲了,什么是最好的解决方案?

阅读全文

作者:Arthur Knopper,原文链接,原文日期:2016-10-18
译者:Crystal Sun;校对:星夜暮晨;定稿:CMB

Segmented Control 用于展示一些用户可以选择的选项。每个 Segment 看起来像是一个单选按钮 (radio button),用户即便选中了某个选项,这个 Segment 仍保持“选中”状态。在本节教程里,我们会在 UISegmentedController 当中创建两个 Segment,每个 Segment 会让 Label 显示不同的文本内容。本节教程将使用 Xcode 8 和 iOS 10 来进行构建。

阅读全文

作者:Natasha The Robot,原文链接,原文日期:2016-09-26
译者:saitjr;校对:小锅;定稿:CMB

目前为止,watchOS 的复用性都不是很好。即使每个界面都差不多,你也不得不在 storyboard 中把所有 Interface Controller 拖出来,就像下面这个 Italian Food 应用一样:



每个 Interface Controller 简单到就只有一个 image 和 label:

即使它们的界面,甚至逻辑都完全一样,在此之前,我都没找到重用这些 Interface Controller 的方法!

所以我有三个不同的 controller,而它们的代码,除了 image 和 label 的数据模型外,其它的我都复制粘贴的。在我坚持不懈下,终于发现了个黑魔法,虽然有点恶心,不过能解决问题倒是真的。

阅读全文

作者:Erica Sadun,原文链接,原文日期:2016-12-06
译者:星夜暮晨;校对:Crystal Sun;定稿:CMB

通常情况下,我更倾向于将 OptionSets 视为一种类型,可惜它们并不是。

public protocol OptionSet : SetAlgebra, RawRepresentable

目前的 OptionSets 是通过协议的方式来实现的,从而使得未来相关 API 的持续演进成为可能。正如 Joe Groff 所指出:开发者可以将单个选项分解为多个精简的选项,与此同时仍然保留提供原始选项的能力。您可以在下面的例子当中看到相应的实现,其组合出了 energyStargentleStar 选项,而它们与那些使用移位标志 (bit-shifted flags) 生成的选项的地位是平等的。

阅读全文

作者:AppCoda,原文链接,原文日期:2016-09-16
译者:ckitakishi;校对:mmoaay;定稿:CMB

CocoaPods 是一个面向 Xcode 的项目依赖管理工具。当需要向项目添加库和框架时,它是一项极其有用且值得选择的服务。

试想一下,有人开发了一个足以改变游戏规则、且具有划时代意义的库,并想把它分享给这个世界。这时候该怎么办?长话短说,我要说的是你需要知道如何发布自己的 CocoaPod!

阅读全文

作者:Umberto Raimondi,原文链接,原文日期:2016-04-07
译者:shanks;校对:pmst;定稿:CMB

从 Swift 开源到现在,只有短短的几个月时间,Swift 却已经被移植到了许多新的平台上,还有一些新的项目已经使用了 Swift。这类移植,每个月都在发生着。

在不同平台下混合使用 Swift 和 C 的可行性,看起来是一件非常难的实践,只有非常有限的实践资源,当然这是和你去封装一个原生库对比起来看的,你可以在你代码运行的平台上轻松地封装一个原生库。

阅读全文

作者:Erica Sadun,原文链接,原文日期:2016/11/3
译者:Cwift;校对:walkingway;定稿:CMB

昨天,一位名叫安德鲁·华纳的开发者撰写的这篇文章引起了一些争论。文章标题“警惕注释的‘塞壬之歌’”(译者注:塞壬是希腊神话中的海妖,她的歌声极具迷惑性,会引起海啸等灾难)暗示了开发人员在自欺欺人,因为注释会降低代码的质量:

注释在腐烂。它们不会被编译,并且永远不会在运行时被执行。如果注释过时或者不正确,测试不会因此而失败,也没有用户会抱怨。和注释打交道的程序员担心“有人可能需要这个注释,或者该注释会对将来的开发带来帮助”,所以在注释真正有用之前就在代码中引入了很多注释(甚至你还得先证明它们的确是有用的)。

他的建议是什么呢?

阅读全文

作者:Erica Sadun,原文链接,原文日期:2016-11-08
译者:星夜暮晨;校对:Crystal Sun;定稿:CMB

不久之前,Iain Delaney 给我发了这一幅图:

这幅由 Steve Luscher 设计的图,其内容来源于 Joey Devilla 的博客 Global Nerdy 中的一篇文章。我觉得这种做法相当有才,让人眼前一亮。

然而,这幅图不是用 Swift 编写的,显然没办法在 Swift 中运行。我决定娱乐一番:我建立了一个 Playground,将大量的 Emoji 字符分配到对应的 Emoji 变量当中,由此构建了一个庞大的列表,然后使用 Swift 的语法让这些例子能够正确运行。

阅读全文

作者:Erica Sadun,原文链接,原文日期:2016-11-17
译者:星夜暮晨;校对:Crystal Sun;定稿:CMB

sssilver 留言说:「我发现我司的代码普遍都是这种情况:每个类都包含了一堆的静态方法。我问同事为什么不直接编写方法,他们回答说是不想污染命名空间。在类似 Rust 之类的语言当中,所有内容都位于模块内部。那么在 Swift 当中常见的做法是如何呢?」

阅读全文

作者:Erica Sadun,原文链接,原文日期:2013-03-15
译者:星夜暮晨;校对:Crystal Sun;定稿:CMB

我现在正在努力地编写那本关于 UIKit / Quartz 的书,书中描述了很多使用 Bezier 路径绘图的案例。今天,在进行了一天忙碌的写作之后,我现在决定好好休息、放松一下。

因此我登上了 IRC (Internet Relay Chat),在那里我遇到了一个很有意思的挑战。它是以 Clarus the dog cow 的形式出现的(译者注:一只像牛的狗,这个卡通形象由苹果传奇图形设计师 SusanKare 设计,在早期的 Mac 系统中,用来显示打印页面的朝向)。这只狗狗是以点阵图 (bitmap) 的形式出现的,通常情况下将其转换为 UIImage 并不是一件很容易的事。当然我觉得,应该有一种通用的方法能够将其转换为可重复使用的路径。

阅读全文

作者:Russ Bishop,原文链接,原文日期:2016-11-07
译者:星夜暮晨;校对:walkingway;定稿:CMB

最近几天,我在 Swift 用户列表中参与了一个讨论,主题是怎样才能更好滴将包含字符串值的 JSON 数组转换为枚举集 (Enumeration Set)。我半开玩笑地建议:这些字符串值应该被转换到基于字符串的枚举当中,然后这些值的 hashValues 将用于设置标志位(flags)。

当然,我很快(并且理所应当)被质疑道:『最终的解决方案是否应该取决于 hashValue 的实现细节』—— 很显然不应该。但是随着我思考的深入,我猜想是否可以通过哈希值来引导选项集 (Option Sets) 的创建,从而消除潜在的错误呢?

阅读全文

作者:GABRIEL THEODOROPOULOS,原文链接,原文日期:2016-11-16
译者:小锅;校对:saitjr;定稿:CMB

自中央处理器(CPU)出现以来,最大的技术进步当属多核处理器,这意味着它可以同时运行多条线程,并且可以在任何时刻处理至少一个任务。

串行执行以及伪多线程都已经成为了历史,如果你经历过老式电脑的时代,又或者你接触过搭载着旧操作系统的旧电脑,你就能轻易明白我的话。但是,不管 CPU 拥有多少个核心,不管它有多么强大,开发者如果不好好利用这些优势 ,那就没有任何意义。这时就需要使用到多线程以及多任务编程了。开发者不仅可以,而且必须要好好利用设备上 CPU 的多线程能力,这就需要开发者将程序分解为多个部分,并让它们在多个线程中并发执行。

并发编程有很多好处,但是最明显的优势包括用更少的时间完成所需的任务,防止界面卡顿,展现更佳的用户体验,等等。想像一下,如果应用需要在主线程下载一堆图片,那种体验有多糟糕,界面会一直卡顿直到所有的下载任务完成;用户是绝对不接受这种应用的。

阅读全文

作者:Andyy Hope,原文链接,原文日期:2016-08-17
译者:Cwift;校对:冬瓜;定稿:CMB

每隔一段时间,你都会遇到一些像独角兽一般前沿的情况,迫使你挑战你在当前的时代与领域内所积累的一切知识。而就在刚才我成为了这种情况的受害者。

在汉语中,“危机”一词由两个字符组成,
一个代表危险,另一个代表机会。
— 约翰·肯尼迪

援引自五十年代末最知名的美国人之一,三十五年后另一个美国人延续了这个话题:

Crisi-tunity!
— 荷马·辛普森

(译者注:分别截取了英文单词 crisis(危险)的前半部分和 opportunity(机会)的后半部分)

阅读全文

作者:Soroush Khanlou,原文链接,原文日期:2016-06-21
译者:Crystal Sun;校对:千叶知风;定稿:CMB

在 Python 中,零和 None,以及空列表、字典和字符串,都有 falsy 值。 如果有 falsy 值,意味着可以它在 if 语句中使用,且可以使用 else。 例如,在 Python 中:

if []:
# will not be evaluated
else:
# will be evaluated

if 0:
# will not be evaluated
else:
# will be evaluated

阅读全文

作者:Soroush Khanlou,原文链接,原文日期:2016-10-13
译者:Cwift;校对:Crystal Sun;定稿:千叶知风

重构是一个持续性的过程。然而,在频繁的重构过程中还需要保证开发的功能可用。如果不能保证,代码就不能被定期部署,这会使得你的代码与团队中其他人的代码保持同步变得更加困难。

即便如此,有一些重构难度额外大。在某些特定的情况中,单例的特性会使其与很多不同的对象耦合,很难从工程中把单例删掉。

许多单例,特别是那些命名很差劲的单例,会逐渐积累无关的行为、数据以及任务,只是因为向单例中增加这些比向其他对象中添加容易很多。

如果想拆分一个影响深远的单例,或者想测试使用单例的代码,就会有很多工作要做。你想用更小、更好的对象慢慢地替换掉单例的引用,但是在完全完成之前不能删除单例本身,因为还有其他的对象依赖它。

最糟糕的是,不能将单例的行为和方法提取到另一个对象中,因为它们依赖于单例内部的共享状态。换句话说,如果单例没有任何共享状态,你可以在每次调用时创建一个新的实例,问题就立马解决了。

有一个单例,包含了许多不同的职责和一堆共享的状态,应用中很多部分都在使用此单例。如何才能在不删除单例代码的情况下解除应用对这个单例的依赖?

阅读全文