1,因为 Swift 是类型安全的,他在编译代码的时候会进行类型检查,任何不匹配的类型都会被标记为错误。这会帮助你在开发阶段更早的发现并修复错误;
2,Swift 在推断浮点值的时候始终会选择 Double (而不是 Float )
3,Swift 中的 nil 和Objective-C 中的 nil 不同,在 Objective-C 中 nil 是一个指向不存在对象的指针。在 Swift中, nil 不是指针,他是值缺失的一种特殊类型,任何类型的可选项都可以设置成 nil 而不仅仅是对象类型
4,与 Objective-C 和 C 不同,Swift 的赋值符号自身不会返回值。下面的语句是不合法的:
5,if x = y { // 这是不合法的, 因为 x = y 并不会返回任何值。}
6,对a % b 与 a % -b ,当 b为负数时,它的正负号会被忽略掉。这意味着 a % b 与 a % -b 能够获得相同的答案,也就是说余数的正负是与被除数的正负有关
7,Swift 标准库包含的元组比较运算符仅支持小于七个元素的元组。要比较拥有七个或者更多元素的元组,你必须自己实现比较运算符
8,闭区间有另外一种形式来让区间朝一个方向尽可能的远——比如说,一个包含数组所有元素的区间,从索引 2 到数组的结束。在这种情况下,你可以省略区间运算符一侧的值。因为运算符只有一侧有值,所以这种区间叫做单侧区间。比如说:
for name in names[2...] { print(name) }
9,Swift 的 String 和 Character 类型提供了一种快速的符合 Unicode 的方式操作你的代码,Swift 的 String类型仍旧是快速和现代的字符串实现。每一个字符串都是由 Unicode 字符的独立编码组成,并且提供了多种 Unicode 表示下访问这些字符的支持,Swift 的 String类型桥接到了基础库中的 NSString类。Foundation 同时也扩展了所有 NSString 定义的方法给 String 。也就是说,如果你导入 Foundation ,就可以在 String 中访问所有的 NSString 方法,无需转换格式。
10,Swift 的 String类型是一种值类型每一次赋值和传递,现存的 String值都会被复制一次,传递走的是拷贝而不是原本,Swift 的默认拷贝 String行为保证了当一个方法或者函数传给你一个 String值,你就绝对拥有了这个 String值。
11,Swift 编译器优化了字符串使用的资源,实际上拷贝只会在确实需要的时候才进行。这意味着当你把字符串当做值类型来操作的时候总是能够有用很棒的性能
12,操作字符:你可以通过 for-in循环遍历 String 中的每一个独立的 Character值,你不能把 String或者 Character追加到已经存在的 Character变量当中,因为 Character值能且只能包含一个字符。
13,字符统计:在字符串中取回 Character值的总数,使用字符串的 count属性,注意 Swift 为 Character值使用的扩展字形集群意味着字符串的创建和修改可能不会总是影响字符串的字符统计数。
14,字符统计:在字符串中取回 Character值的总数,使用字符串的 count属性,注意 Swift 为 Character值使用的扩展字形集群意味着字符串的创建和修改可能不会总是影响字符串的字符统计数。
15,每一个 String值都有相关的索引类型, String.Index,它相当于每个 Character在字符串中的位置。
16,不同的字符会获得不同的内存空间来储存,所以为了明确哪个 Character 在哪个特定的位置,你必须从 String的开头或结尾遍历每一个 Unicode 标量。因此,Swift 的字符串不能通过整数值索引;使用 index(before:) 和 index(after:) 方法来访问给定索引的前后。要访问给定索引更远的索引,你可以使用 index(_:offsetBy:) 方法而不是多次调用这两个方法。
17,尝试访问的 Character如果索引位置在字符串范围之外,就会触发运行时错误。使用 characters属性的 indices属性来创建所有能够用来访问字符串中独立字符的索引范围 Range;
for index in greeting.characters.indices {
print("\(greeting[index]) ", terminator: "")
}
18,你可以在任何遵循了 Indexable 协议的类型中使用 startIndex 和 endIndex 属性以及 index(before:) , index(after:) 和 index(_:offsetBy:) 方法。这包括这里使用的 String ,还有集合类型比如 Array , Dictionary 和 Set。
19,要移除一小段特定范围的字符串,使用 removeSubrange(_:) 方法:let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex;
welcome.removeSubrange(range);
20,你可以在任何遵循了 RangeReplaceableIndexable 协议的类型中使用 insert(_:at:) , insert(contentsOf:at:) , remove(at:) 方法。这包括了这里使用的 String ,同样还有集合类型比如 Array , Dictionary 和 Set 。
21,访问和修改数组:使用布尔量 isEmpty属性来作为检查 count属性是否等于 0的快捷方式;
可以使用加赋值运算符 ( +=)来在数组末尾添加一个或者多个同类型元素:shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
可以使用下标脚本语法来一次改变一个范围的值,就算替换与范围长度不同的值的合集也行:shoppingList[4...6] = ["Bananas", "Apples"]。
22,如果你需要每个元素以及值的整数索引,使用 enumerated()方法来遍历数组。 enumerated()方法返回数组中每一个元素的元组,包含了这个元素的索引和值:for (index, value) in shoppingList.enumerated() {
print("Item \(index + 1): \(value)")
}
23,Set合集类型不能从数组字面量推断出来,所以 Set类型必须被显式地声明;合集将同一类型且不重复的值无序地储存在一个集合当中。当元素的顺序不那么重要的时候你就可以使用合集来代替数组,或者你需要确保元素不会重复的时候。
24,基本合集操作:
使用 intersection(_:)方法来创建一个只包含两个合集共有值的新合集;
使用 symmetricDifference(_:)方法来创建一个只包含两个合集各自有的非共有值的新合集;
使用 union(_:)方法来创建一个包含两个合集所有值的新合集;
使用 subtracting(_:)方法来创建一个两个合集当中不包含某个合集值的新合集;
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
25,使用“相等”运算符 ( == )来判断两个合集是否包含有相同的值;
使用 isSubset(of:) 方法来确定一个合集的所有值是被某合集包含;
使用 isSuperset(of:)方法来确定一个合集是否包含某个合集的所有值;
使用 isStrictSubset(of:) 或者 isStrictSuperset(of:)方法来确定是个合集是否为某一个合集的子集或者超集,但并不相等;
使用 isDisjoint(with:)方法来判断两个合集是否拥有完全不同的值。
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
26,字典类型: 可 (以Int类型)为键值,例如:var namesOfIntegers = [Int: String]();使用 stride(from:to:by:) 函数来跳过不想要的标记;
let minutes = 60
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
// render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55) //【小于60】
}
27,闭区间也同样适用,使用 stride(from:through:by:) 即可:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// render the tick mark every 3 hours (3, 6, 9, 12) //可等于12
}
28,switch没有隐式贯穿:相比 C 和 Objective-C 里的 switch 语句来说,Swift 里的 switch 语句不会默认从每个情况的末尾贯穿到下一个情况里。相反,整个 switch 语句会在匹配到第一个 switch 情况执行完毕之后退出,不再需要显式的 break 语句。
29,在一个 switch 情况中匹配多个值可以用逗号分隔,并且可以写成多行:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
}
// Prints "The letter A"
30,区间匹配: case 1..<5
元组:
你可以使用元组来在一个 switch 语句中测试多个值。每个元组中的元素都可以与不同的值或者区间进行匹配。另外,使用下划线( _)来表明匹配所有可能的值;
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("(0, 0) is at the origin")
case (_, 0):
print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
print("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
print("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
print("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
31,switch 情况可以将匹配到的值临时绑定为一个常量或者变量,来给情况的函数体使用。这就是所谓的值绑定,
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
32,switch 情况可以使用 where 分句来检查额外的情况
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
33,复合情况:
多个 switch 共享同一个函数体的多个情况可以在 case 后写多个模式来复合,在每个模式之间用逗号分隔。
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
34,复合情况同样可以包含值绑定。所有复合情况的模式都必须包含相同的值绑定集合,并且复合情况中的每一个绑定都得有相同的类型格式。这才能确保无论复合情况的那部分匹配了,接下来的函数体中的代码都能访问到绑定的值并且值的类型也都相同。
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
print("On an axis, \(distance) from the origin")
default:
print("Not on an axis")
}
35,控制转移语句有五种:continue,break,fallthrough,return,throw;如果你确实需要 C 风格的贯穿行为,你可以选择在每个情况末尾使用 fallthrough 关键字,
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
它使用 fallthrough 关键字来“贯穿到” default 情况。 default 情况添加额外的文字到描述的末尾,接着 switch 语句结束;fallthrough 关键字不会为switch情况检查贯穿入情况的条件。 fallthrough 关键字只是使代码执行直接移动到下一个情况(或者 default 情况)的代码块中,就像C的标准 switch 语句行为一样。
36,guard 语句总是有一个 else 分句—— else 分句里的代码会在条件不为真的时候执行。if #available(iOS 10, macOS 10.12, *) 最后一个实际参数, * ,它需求并表明在其他所有平台, if 函数体执行你在目标里明确的最小部属;
37,类似 (Int, Int)?的可选元组类型和包含可选类型的元组 (Int?, Int?)是不同的。对于可选元组类型,整个元组是可选的,而不仅仅是元组里边的单个值。
38,输入输出形式参数:
如果你想函数能够修改一个形式参数的值,而且你想这些改变在函数结束之后依然生效,那么就需要将形式参数定义为输入输出形式参数。
在形式参数定义开始的时候在前边添加一个 inout关键字可以定义一个输入输出形式参数。输入输出形式参数有一个能输入给函数的值,函数能对其进行修改,还能输出到函数外边替换原来的值。输入输出形式参数不能有默认值,可变形式参数不能标记为 inout,如果你给一个形式参数标记了 inout,那么它们也不能标记 var和 let了;
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
39,reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
从语境中推断类型:
因排序闭包为实际参数来传递给函数,故 Swift 能推断它的形式参数类型和返回类型。 sorted(by:) 方法期望它的第二个形式参数是一个 (String, String) -> Bool 类型的函数。这意味着 (String, String)和 Bool 类型不需要被写成闭包表达式定义中的一部分,因为所有的类型都能被推断,返回箭头 ( ->) 和围绕在形式参数名周围的括号也能被省略:
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
从单表达式闭包隐式返回:
单表达式闭包能够通过从它们的声明中删掉 return 关键字来隐式返回它们单个表达式的结果,前面的栗子可以写作:
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )