作者:Dominik Hauser,原文链接,原文日期:2016-04-19
译者:Darren;校对:Crystal Sun;定稿:CMB

昨天有人问我, Swift 初学者应该先学什么。 问题是这样的:

我有个问题想咨询一下你, 是应该花时间学习 TDD (测试驱动开发) , 还是应该学习 Swift 和函数式编程,哪样更值得学习?

当然,我的观点会有一些偏见,因为我写了一本关于 Swift TDD 的书。在看我的回答时,切记这一点。

阅读全文

作者:Andyy Hope,原文链接,原文日期:2016-07-20
译者:X140yu;校对:walkingway;定稿:CMB

↑ ↑ ↓ ↓ ← → ← → B A

无论是你学习的第一门语言是 Swift 还是之前学过 Objective-C,在学习 Swift 的过程中,一定会感叹它真的是一门超赞的语言。但如果你不熟悉它的某些语法,就可能会被某些写法吓到。在这里我会介绍一些在写 Swift 过程中常见语法,希望你们能用 Swift 写出更简洁的代码。

阅读全文

作者:Arthur Knopper,原文链接,原文日期:2016-06-01
译者:TonyHan;校对:walkingway;定稿:CMB

让观察者模式变得更美好

OSX 已经有至少 17 年的历史,而 NotificationCenter 在其第一次版本发布就已经存在,并且一直是苹果开发者常用的工具。对于不了解的人来说,NotificationCenter 是基于 观察者模式 的概念,也是软件设计模式中行为型模式的一部分。

阅读全文

作者:Arthur Knopper,原文链接,原文日期:2017/04/05
译者:Crystal Sun;校对:walkingway;定稿:CMB

picker view 看起来像是自动贩售机或者角子老虎机,用于展示一组或者多组数值。用户通过滚轮来选择数值,选中的值处在同一行中。Xcode 里的 User Interface 提供了 picker view 控件,展示可选的组件和行。组件就是滚轮,有很多行,每行都有固定的 index 值。本教程使用的是 Xcode 8.3 和 iOS 10.3。

阅读全文

作者:Arthur Knopper,原文链接,原文日期:2017-01-09
译者:钟颖Cyan;校对:Cwift;定稿:CMB

通过长按手势来展示上下文菜单,给了用户对选中对象进行 剪切/复制/粘贴 操作的能力。在默认情况下,Table View 的上下文菜单是禁止的。在本文中,使用上下文菜单复制 Table View Cell 上面的文字,随后可以将文字粘贴到 Text Field 里面。本教程基于 Xcode 8.1 和 iOS 10。

阅读全文

作者:Arthur Knopper,原文链接,原文日期:2015-12-22
译者:钟颖Cyan;校对:Cwift;定稿:CMB

译者注:由于原文日期较早,文章代码已更新为新版本。

UITextChecker 对象可以用来对一个字符串进行拼写检查,在这篇教程里面我们将在一个 Table View 里面展示一些单词。当单词被选中的时候,会被进行拼写检查,拼写正确的背景将会变成绿色,否则将会变成红色。本教程在 Xcode 7.2 和 iOS 9 环境下进行。

阅读全文

作者:Ole Begemann,原文链接,原文日期:2017-02-08
译者:四娘;校对:Cwift;定稿:CMB

上周的 Swift Talk 里,Florian 和 Chris 编写了一个有序数组类型 SortedArray:一个总是按照指定规则排序的数组。这很赞,因为它将多个不变性编码到了类型系统里。用户可以使用这个类型去取代普通的 数组 ,而且不用担心忘记手动排序数组。

为了保持视频简短,Florian 和 Chris 省略掉了一些很实用的功能。我想给你展示一下这部分实用功能的实现。这些实现都不难编写,我的主要目的是让你明白借助标准库去实现一个紧贴需求的自定义集合类型是多么简单。

你可以去 GitHub 上查看全部代码 ,但下面会有更多讲解。

阅读全文

作者:Ole Begemann,原文链接,原文日期:2017/3/6
译者:Cwift;校对:walkingway;定稿:CMB

有时候为了新增一个功能,会去修改你的 ViewController 。但代码总是环环相扣的,你会发现在 ViewController 中引入一个可选型的属性时,在某些情况下该属性会被赋值,而在另一些情况下它不会被赋值。

我认为大多数情况下,这种方案是有缺陷的。原因有几点。首先,当一个类含有未使用的可选型属性时,这个类中描述身份的语义会变弱。换句话说,添加可选型属性会模糊 类型的基本语义 。第二,可选型的属性不带任何语义。如果该属性的值是 nil ,那么当前对象处于什么状态呢?如果别人只是粗略浏览你的代码,并不能搞清楚什么情况下属性会是 nil ,或者如果属性是 nil 的话对对象本身有什么影响。第三,代码会继续发生变异。一个可选型的属性会变成两个,然后变成三个,等你发现的时候已经掉坑里了。在某个值还是 nil 的时候你想要表达出该值当前必须存在的意愿,仅靠普通的可选型是办不到的。

在我见过的代码库中,我发现有两种原因可能会致使你在 ViewController 中添加一个可选型的属性。我会对这些情况进行探索,提出有针对性的更好的解决方案。

阅读全文

作者:Ole Begemann,原文链接,原文日期:2017-03-08
译者:Cwift;校对:walkingway;定稿:CMB

假设你有一个结构体:

struct Person {
var name: String
}

并且让其遵守 Equatable

extension Person: Equatable {
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name
}
}

实际的效果满足预期:

Person(name: "Lisa") == Person(name: "Lisa") // → true
Person(name: "Lisa") == Person(name: "Bart") // → false

阅读全文

作者:Soroush Khanlou,原文链接,原文日期:2016-08-01
译者:Cwift;校对:walkingway;定稿:CMB

Promise 是一种链接异步任务的方式。通常来说,异步任务会在异步操作完成时执行回调闭包(有时候要准备两个闭包,一个代表成功,一个代表失败)。要执行多个异步操作,必须将第二个异步操作放在第一个异步操作的完成闭包中执行:

APIClient.fetchCurrentUser(success: { currentUser in
APIClient.fetchFollowers(user: currentUser, success: { followers in
//现在你得到了一个 followers 数组
}, failure: { error in
// 错误处理
})
}, failure: { error in
// 错误处理
})

Promise 的作用是格式化完成闭包,简化链式异步调用的形式。如果系统能够分辨成功和失败,那么组合这些异步操作就变得容易很多。比如,编写具有下列功能的可重用代码:

  • 使用尾闭包执行一系列依赖关系的异步操作
  • 通过一个完成闭包同时执行多个独立的异步操作
  • 多个异步操作竞争,返回第一个完成的值
  • 重试异步操作
  • 为异步操作设置超时时间

阅读全文

作者:Yari D’areglia,原文链接,原文日期:2017-01-03
译者:SketchK;校对:Cee;定稿:CMB

在我看来,3D Touch 是能够追踪用户按压屏幕力度、并且是 iOS 的触碰处理中最有意思且未被充分挖掘的一个能力特性。

通过这个教程,我们会创建一个自定义的按钮,并且要求用户通过 3D Touch 操作进行确认。如果用户的设备不支持 3D Touch,控件对用户的处理也会回退到备选方案。下面是预览视频,它能够让你快速了解这个自定义控件是如何工作的:





  1. 当用户开始点击屏幕时,一个圆形的进度条就会跟踪用户按压屏幕的力度。用户按压屏幕的力度会影响圆形视图填充进度,按得越用力,圆就被填充得越多(稍后我会展示在不支持 3D Touch 的设备上模拟该行为)。

  2. 当圆形被填充满的时候,它会变成一个处于激活状态的按钮,圆形进度条里的标签内容会变成 “OK” 且颜色变成绿色,这暗示着当前操作可以被确认。此时用户可以通过向上滑动手指并在圆圈上松开手指的方式来确认此操作。

通常,我们会通过弹窗的方式来询问用户是否想进行一个删除操作。我很乐意做一些 UX 交互方面的尝试,而且我认为 3D Touch 这种新的交互方式可以很好的替代原有的 “标准” 交互流程。你真的应该在一个实体机上体验一下 3D Touch,马上你就会了解到交互的便利性。😀

阅读全文

作者:Ole Begemann,原文链接,原文日期:2017-03-06
译者:Cwift;校对:numbbbbb;定稿:CMB

假设你有一个 Swift 的枚举:

enum Expression {
case number(Double)
case string(String)
}

你希望它遵守 Equatable 协议。由于该枚举具有关联值,必须手动添加,所以需要实现 == 函数

extension Expression: Equatable {
static func ==(lhs: Expression, rhs: Expression)
-> Bool {
switch (lhs, rhs) {
case let (.number(l), .number(r)): return l == r
case let (.string(l), .string(r)): return l == r
default: return false
}
}
}

这里处理了参数类型相同的两种情况,比较类型不同时会执行 default case 并返回 false。这种做法简单直接,也没错:

Expression.number(1) == .number(1) // → true
Expression.number(1) == .string("a") // → false

阅读全文

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

本周在 Swift 进化 板块,有一个有趣的(且争论很久的)讨论。 有人建议在 Swift 标准库中添加一个名为 DefaultConstructible 的协议,其唯一的要求是提供一个无参数的构造器:

protocol DefaultConstructible {
init()
}

换个说法,用协议的方式规范以下概念:你可以创建某种类型的“默认”值,或者说当没有附加信息时也能得到一个遵守协议的实例。

有一些人,比如 Xiaodi WuDave Abrahams,提出了一些非常好的论据来反对这个观点。在这里我再次重复一次这些观点,因为我觉得相比这个具体的话题,他们所讨论的内容有着更加广泛的意义。

阅读全文

作者:Soroush Khanlou,原文链接,原文日期:2016-10-25
译者:wiilen;校对:Cwift;定稿:CMB

要使用 NSCoding,必须遵循 NSObjectProtocol 这个类协议,因此结构体无法使用。如果我们想对某些数据进行编码,最简单的方式是将它们作为一个类来实现,并且继承自 NSObject

我找到了一种优雅的方式来将结构体包在 NSCoding 的容器中,存储时也不会让人觉得小题大做。用 Coordinate 举个例子:

阅读全文

作者:uraimo,原文链接,原文日期:2017-02-05
译者:pmst;校对:Yake;定稿:CMB

有人建议我写一个小型语言解释器,如果是 LISP 那就更完美了。作为一名程序员,这是你职业生涯必须经历的事情之一,也是一次让你大开眼界的经历:你会对日常工作中的工具产生新的见解,那些令人望而生畏的概念也会被慢慢掀开神秘的面纱。

本文中,我们基于 1978 年 John McCarthy 发表的 A Micro-Manual For Lisp - Not The Whole Thruth 文章,实现一个小型 LISP 解释器,麻雀虽小但五脏俱全,这里主要利用 Swift 框架来对一些包含 LISP 符号表达式的字符串解释。

我们最终会使用解释器来构建一个简单的 REPL (Read-Eval-Print-Loop) 程序,它将交互地执行语句并打印出求值结果。我们还实现了探究解释器的一个 Playground 。

本文将手把手教你直至完成属于你的 LISP 解释器,这将是一次难忘的周末计划。选择跟着一起实现或只是阅读介绍取决于你的心情,当然你也可以参考本文的实现,构建你独有的解释器。

下图显示了我们将要建造的总体设计:

阅读全文

作者:Ole Begemann,原文链接,原文日期:2017-02-07
译者:Cwift;校对:walkingway;定稿:CMB

本系列的其他文章:
(1)Dictionary and Set
(2)String.CharacterView(本文)

上一篇文章 中,我讨论了为什么 Set 和 Dictionary 不能遵守 MutableCollection 和 RangeReplaceableCollection。今天轮到 String.CharacterView 了。

CharacterView 遵守了 RangeReplaceableCollection,但不能遵守 MutableCollection。这是为什么呢?字符串明显是可变的; 从逻辑来看它应该遵守 MutableCollection 协议。我们需要再次回过头来考虑下协议的语义

MutableCollection 的文档制定了以下要求:

MutableCollection 协议允许更改集合中元素的值,但不允许更改集合本身的长度…
在 MutableCollection 实例的某个下标位置保存的值,之后必须可以在同一位置访问。也就是说,对于可变集合实例 a,索引 i 和值 x,以下代码示例中的两组赋值必须是等价的:

a[i] = x
let y = a[i]
// 必须等同于
a[i] = x
let y = x

阅读全文

作者:Nick Hanan,原文链接,原文日期:2016-03-17
译者:BigbigChai;校对:walkingway;定稿:CMB

许多应用程序都有访问文件的需求。也许是应用 bundle 或文件系统的文件,又或许是网上的资源。在代码里需要调用某些方法来指向这些文件。对于 Apple 平台而言,基本上只有两个选择:使用 String 或 NSURL。

使用过地址栏或任何终端的话,Swift 字符串将是一个非常容易理解的选择。我的意思是,所有的文本都是在地址栏的,对吧?Cocoa 和 Cocoa Touch SDK 中一些较旧的 API 都接收 NSURL 和字符串(通常在这些 API 中称为“路径”)作为参数,但是都越来越朝着只使用 NSURL 的方向发展。和 String 路径相比,NSURL 有许多优点,最明显的是可以访问 URL 各个部分的属性,而不必另外编写代码来从路径的字符串解析出这些组件。

请继续关注如何在 Swift 应用程序中学习创建和使用 NSURL。

阅读全文

作者:Andyy Hope,原文链接,原文日期:2016-04-14
译者:SketchK;校对:Crystal Sun;定稿:CMB

时尚日志,由你做主

之前的文章中,我们讨论了在输出日志中使用 emojis 的好处,它可以帮助我们更好的去消化和吸收海量的信息。不过我提供的实现方式并不怎么样,估计你也不会想把这些东技术用到自己的代码中去。

不管怎么样,我还是会遵守之前的约定继续讨论这个话题,向你展示如何使用 emojis 来实现输出日志的功能,而你只需在 print 函数上再多花费一点儿工夫。

阅读全文