default 参数
Swift 的方法是支持默认参数的,也就是说在声明方法时,可以给某个参数指定一个默认使用的值。在调用该方法时要是传入了这个参数,则使用传入的值,如果缺少这个输入参数,那么直接使用设定的默认值进行调用。Swift对默认参数在参数列表中的位置没有限制。
func sayHello1(str1: String = "Hello", str2: String, str3: String) {
print(str1 + str2 + str3)
}
func sayHello2(str1: String, str2: String, str3: String = "World") {
print(str1 + str2 + str3)
}
sayHello1(str2: "", str3: "World")
sayHello2(str1: "Hello", str2: "")
// 输出都是 Hello World
我们可能会注意到 NSLocalizedString
这个常用方法的签名现在是:
public func NSLocalizedString(_ key: String,
tableName: String? = default,
bundle: Bundle = default,
value: String = default,
comment: String) -> String
默认参数写的是 default
,这是含有默认参数的方法所生成的 Swift 的调用接口。当我们指定一个编译时就能确定的常量来作为默认参数的取值时,这个取值是隐藏在方法实现内部,而不应该暴露给其他部分。类似的还有Swift中的各类断言:
public func assert(_ condition: @autoclosure () -> Bool,
_ message: @autoclosure () -> String = default,
file: StaticString = #file,
line: UInt = #line)
... 和 ..<
Swift 中对 ...
和 ..<
两个操作符的定义:
/// Returns a closed range that contains both of its bounds.
public func ...<Bound>(minimum: Bound, maximum: Bound) -> ClosedRange<Bound> where Bound : Comparable
/// Returns a countable closed range that contains both of its bounds.
public func ...<Bound>(minimum: Bound, maximum: Bound) -> CountableClosedRange<Bound> where Bound : Comparable, Bound : _Strideable, Bound.Stride : SignedInteger
/// Returns a half-open range that contains its lower bound but not its upper bound.
public func ..<<Bound>(minimum: Bound, maximum: Bound) -> Range<Bound> where Bound : Comparable
/// Returns a countable half-open range that contains its lower bound but not its upper bound.
public func ..<<Bound>(minimum: Bound, maximum: Bound) -> CountableRange<Bound> where Bound : Comparable, Bound : _Strideable, Bound.Stride : SignedInteger
不难发现,其实这几个方法都是支持泛型的。这两个操作符接受一个实现 Comparable
协议的输入,并返回一个任意类型的并且符合Comparable
协议的 Range
。在 Swift 中,除了数字以外另一个实现了 Comparable
的基本类型就是 String
。也就是说我们可以通过 ...
或者 ..<
来连接两个字符串。一个常见的使用场景就是检查某个字符是否是合法的字符。比如想确认一个单词里的全部字符都是小写英文字母的话,可以这么做:
let test = "helLo"
let interval = "a"..."z"
for c in test.characters {
if !interval.contains(String(c)) {
print("\(c) 不是小写字母");
}
}
// L 不是小写字母
在日常开发中,我们可能会需要确定某个字符是不是有效的 ASCII 字符,和上面的例子很相似, 我们可以使用 \0...~
这样的 closeInterval
来进行 ( \0
和 ~
分别是 ASCII 的第一个和最后一 个字符)。
第三个方法的使用示例:
let lessThanFive = 0.0..<5.0
print(lessThanFive.contains(3.14)) // Prints "true"
print(lessThanFive.contains(5.0)) // Prints "false"
第二个和第四个方法使用区间操作符 ...
和 ..<
来创建一个任意类型的闭区间和开区间,这个区间符合 Strideable
协议,有一个关联的有符号整数 Stride
类型,如标准库中的任意一个整型。你可以对这个符合 Strideable
协议的区间使用 Sequence
和 Collection
的方法。例如:
let singleDigits = 0...9
print(singleDigits.contains(9)) // Prints "true"
// 你可以对 singleDigits 区间使用 sequence or collection 的方法.
print(singleDigits.count) // Prints "10"
print(singleDigits.last) // Prints "9"
let upToFive = 0..<5
print(upToFive.contains(3)) // Prints "true"
print(upToFive.contains(5)) // Prints "false"
// You can use sequence or collection methods on the `upToFive` countable range.
print(upToFive.count) // Prints "5"
print(upToFive.last) // Prints "4"
print 和 debugPrint
对某个特定的类型使用 CustomStringConvertible
协议,这个协议定义了将该类型实例输出时所用的字符串。相对于直接在原来的类型定义中进行更改,我们更应该倾向于使用一个 extension
,这样不会使原来的核心部分的代码变乱变脏,是一种很好的代码组织的形式:
extension Meeting: CustomStringConvertible {
var description: String {
return "于 \(self.date) 在 \(self.place) 与 \(self.attendeeName) 进行会议 "
}
}
CustomDebugStringConvertible
与 CustomStringConvertible
的作用很类似,但是仅发生在调试中使用 debugger 来进行打印的时候的输出。对于实现了 CustomDebugStringConvertible
协议的类型,我们可以在给 meeting
赋值后设置断点并在控制台使用类似 po meeting
的命令进行打印,控制台输出将为 CustomDebugStringConvertible
中定义的 debugDescription
返回的字符串。
extension Meeting: CustomDebugStringConvertible {
var debugDescription: String {
return "于\(self.date) 在 \(self.place) 与 \(self.attendName) 进行会议"
}
}
debugPrint(meeting)