Basic Operators
Assignment Operator
可以同时赋值多个变量哦(利用元组)~
let (x, y) = (1, 2)
// x is equal to 1, and y is equal to 2
与C和OC不同的是,赋值语句不能用于bool判断哦,其实还是那个就是bool判断非常严格,当然这也是为了防止你弄混==
和=
if x = y {
// this is not valid, because x = y does not return a value
}
Arithmetic Operators
算术运算符(+,-,*,/,%等)会检测并不允许值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见溢出运算符。
这里+
号可以用于连接Character以及String哦~
Remainder Operator
Swift中对于负数的这种操作,严格来说是一个取余运算而不是一个模运算。
a= (b x some multiplier) +remainder
// some multiplier是在满足最接近a的前提下b的最大乘数。
例如9%4=1
,-9%4=-1
,在对负数b求余时,b的符号会被忽略。这意味着a % b和a % -b的结果是相同的。
注意-9%4=-1而非3,-5%-3=-2而非1,所以对负数而言, (b x some multiplier)需要大于它,和正数相反。
也就是a为负,remainder也为负;a为正,remainder也为正。
Floating-Point Remainder Calculations
和OC以及C不同的是,%可以用于浮点数,但swift3以后已经不行了哦,需要用truncatingRemainder
替代:
print(8%2.5) // 错的
print(2.5.truncatingRemainder(dividingBy: 1.1)) // 对的,结果0.2999999999999998
对负数和之前正数是一样的哦
Increment and Decrement Operators
一元运算符(-)直接放在运算对象前,没有任何空格。尽管+实质上什么都没做,但是当在代码中使用了-时,可以用+提供对称性。
Compound Assignment Operators
组合赋值运算符并不返回一个值。例如,不能写成let b = a += 2。
Comparison Operators
Swift同样提供了两个恒等运算符 (
===
和!==
),他们用来检查两个对象指针是否指向了同一个对象实例。
Closed Range Operator
闭区间运算符 (a...b)定义了一个从a到b,并且包括a和b的范围。a的值必须小于b的值。
当遍历一个范围内的所有值时,闭区间运算符非常有用,例如一个for-in循环:
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
Half-Closed Range Operator
半开区间运算符 (a..<b)定义了一个从a到b,但不包括b的范围。之所以称为半开 是因为它包括第一个值,但是不包含最后一个值。和闭区间运算符一样,a的值必须小于b的值。如果a的值等于b的值,那么区间就是空的。
当处理以0为基数的列表例如数组时,半开区间运算符是极其有用的,这里它可以计数到但是不包括列表的长度:
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
print("Person \(i + 1) is called \(names[i])")
}
Strings and Characters
一个字符串是一系列字符的集合,例如hello, world和albatross。Swift的字符串是String类型。可以通过不同访问字符串的内容,例如作为Character值的集合。
Swift的
String
类型与Foundation框架的NSString
类进行了桥接。Foundation框架同样扩展了String
来暴露NSString
的方法。这意味着如果你引入了Foundation框架,可以在String
上直接调用NSString
的方法而无需转换。
更多关于结合Foundation和Cocoa使用String
的内容,详见Using Swift with Cocoa and Objective-C (Swift 3.0.1)的Working with Cocoa Data Types。
Initializing an Empty String
var emptyString = "" // empty string literal
var anotherEmptyString = String() // initializer syntax
// these two strings are both empty, and are equivalent to each other
可以通过属性来判断字符串是不是空:
if emptyString.isEmpty {
println("Nothing to see here")
}
String Mutability
一个指定的字符串是否可变取决于它被赋值为一个常量还是变量:
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// this reports a compile-time error - a constant string cannot be modified
在OC与Cocoa中,通过选择使用NSString或者NSMutableString来决定一个字符串是否可变,这种处理方式和Swift是不同的。
Strings Are Value Types
Swift的
String
类型是一个值类型。创建一个新的String
值,当它被传递到一个函数或者方法,或者被赋值给一个常量或则变量时,它的值是被复制的。在每种情况下,都创建了一个已知值的副本,然后这个副本被传递或者赋值,而不是原始的值。值类型会在结构体和枚举是值类型介绍。这和OC中的NSString是不一致的,OC中传递NSString的时候其实传递的是指针。
String
这种默认的值拷贝行为确保了当一个函数或者方法传入了一个String
值时,你清晰的知道你拥有这个确切的String
值,而无需考虑它的来源。你可以很自信的认为你传入的String
值不会被修改,除非你自己修改了它。
实际上,Swift的编译器会最优化字符串的使用,所以实际的拷贝只会发生在绝对必要时。这意味着当把一个字符串作为值类型处理时总能获取到最优的性能。
Working with Characters
可以通过在for-in循环中遍历一个字符串的characters属性来获取它的每一个Character值。
for character in "Dog!🐶".characters {
print(character)
}
// D
// o
// g
// !
// 🐶
如果你想初始化一个字符,需要指明类型哦,否则和string无法区分:
let yenSign: Character = "¥"
Counting Characters
如果想要获取一个字符串中Character值的数量,使用字符串的Character属性的count属性:
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// Prints "unusualMenagerie has 40 characters"
注意在Swift中,使用可扩展的字符簇作为Character值意味着字符串的连接或者修改并不一定会影响字符串的字符数量。
例如,如果使用四个字符长度的单词cafe初始化一个新的字符串,然后在尾部拼接一个COMBINING ACUTE ACCENT (U+0301),结果仍然是含有4个字符,第四个字符是é而不是e:
var word = "cafe"
print("the number of characters in \(word) is \(word.characters.count)")
// Prints "the number of characters in cafe is 4"
word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
print("the number of characters in \(word) is \(word.characters.count)")
// Prints "the number of characters in café is 4"
可扩展的字符簇可以由多个Unicode标量构成。这意味着不同的字符以及相同字符的不同表示方式可以请求不同的存储空间。因此Swift的字符在一个字符串中并不一定占据相同的存储空间。所以在没有遍历整个字符串确定它的可扩展的字符簇边界时是不能计算字符的数量的。如果处理一个特别长的字符值,需要注意Character属性必须遍历整个字符串的所有Unicode标量才能确定字符的数量。
通过Character属性返回的字符数量并不总是和包含相同字符的通过NSString的length属性返回的长度相同。NSString的长度是基于字符串在UTF-16表示方式下16位码元的数量而不是Unicode可扩展字符簇的数量。
String Equality
Swift提供了三种方式比较文本值:字符串和字符相等,前缀相等,后缀相等。
使用等于运算符(==)和不等于运算符(!=)检查字符串和字符的等同性:
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
如果两个String值或者两个Character值的可扩展的字符簇是相等的那么它们两个就认为是相等的。如果可扩展的字符簇有同样的语义和外观就认为它们是相等的,即使它们实际上是由不同的Unicode标量构成。
例如,LATIN SMALL LETTER E WITH ACUTE(U+00E9)等于LATIN SMALL LETTER E(U+0065)加上COMBINING ACUTE ACCENT(U+0301)。这些可扩展的字符簇都是合法的方式代表字符é,所以它们被认为是相等的。
// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
// "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
if eAcuteQuestion == combinedEAcuteQuestion {
print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
相反的,英语中使用的LATIN CAPITAL LETTER A(U+0041或者A)与俄语中的CYRILLIC CAPITAL LETTER A(U+0410或者А)是不相等的。这两个字符只是视觉上相似,但没有相同的语义:
let latinCapitalLetterA: Character = "\u{41}"
let cyrillicCapitalLetterA: Character = "\u{0410}"
if latinCapitalLetterA != cyrillicCapitalLetterA {
print("These two characters are not equivalent.")
}
// Prints "These two characters are not equivalent."
注意Swift的字符串和字符比较并不区分地域。
使用字符串的hasPrefix(_:)
和hasSuffix(_:)
方法检测一个字符串是有有一个指定的字符前缀或者后缀,这两个方法都使用一个单独的String类型参数并返回一个布尔值。
Uppercase and Lowercase Strings
可以直接获取string的大写/小写格式哦:
let normal = "Could you help me, please?"
let shouty = normal.uppercaseString
// shouty is equal to "COULD YOU HELP ME, PLEASE?" let whispered = normal.lowercaseString
// whispered is equal to "could you help me, please?"
Unicode
一个unicode字符可以被1个或者多个unicode scalars标量组成,1个unicode scalars是21位bit的number,例如U+0061
就是小写的"a"。
当向一个文本文件或者一些其它储存器写入一个Unicode字符串时,字符串的Unicode标量会使用Unicode定义的几种编码格式编码。每种格式都会将字符串编码进小的块,也就是码元。
这些包括UTF-8编码格式(将字符串编码成8位的码元),UTF-16编码格式(将字符串编码成16位的码元),UTF-32编码格式(将字符串编码成32位的码元)。
可以使用for-in
声明遍历字符串来以可扩展的字符簇的形式访问它的每个Character
值。详见使用字符串。
同样可以以另外三种Unicode兼容的表现形式访问一个String
值:
- UTF-8码源的集合(通过
utf8
属性访问) - UTF-16码源的集合(通过
utf16
属性访问) - 21位Unicode标量值的集合,等于字符串的UTF-32编码格式(通过
unicodeScalars
属性访问)
UTF-8
var str0 = "sd"
for utf8 in str0.utf8 {
print(utf8)
}
输出:
115
100

上例中,前3个十进制codeUnit值(68, 111, 103)代表了字符D,o和g,这些字符的UTF-8形式和它们的ASCII形式是一样的。接下来的3个十进制codeUnit值(226, 128, 188)是字符DOUBLE EXCLAMATION MARK的三位UTF-8形式。最后的的4个十进制codeUnit值(240, 159, 144, 182)是字符DOG FACE的四位UTF-8形式。
UTF-16
var str0 = "sd"
for utf16 in str0.utf16 {
print(utf16)
}
输出:
115
100

同样的,前3个codeUnit值(68, 111, 103)代表了字符D,o和g,这些字符的UTF-16码元和它们的UTF-8形式有同样的值(因为这些Unicode标量代表ASCII字符)。
第四个codeUnit值(8252)是一个等同于16进制值203C的十进制值,它代表了字符DOUBLE EXCLAMATION MARK的Unicode标量U+203C。这个字符可以被表示成一个单独的UTF-16码元。
第五和第六个codeUnit值 (55357和56374) 是字符DOG FACE的 UTF-16 表示。这些值为U+D83D(十进制值为55357)的高代理值,和U+DC36(十进制值为56374)的低代理值。
Unicode Scalars
var str0 = "sd"
for char0 in str0.unicodeScalars {
print(char0)
}
输出:
s
d
for char0 in str0.unicodeScalars {
print(char0.value)
}
输出:
115
100

可以通过遍历字符串的unicodeScalars属性来访问字符串的Unicode标量形式。这个属性是UnicodeScalarView类型的,这个类型是一个UnicodeScalar类型值的集合。
每个unicodeScalars有一个value属性返回这个标量的21位值,用UInt32。
前三个UnicodeScalar值(68,111,103)的value属性仍然代表字符D、o和g。第四个codeUnit值(8252)仍然是一个等于十六进制203C的十进制值。它代表了DOUBLE EXCLAMATION MARK字符的Unicode标量U+203C。
第五个UnicodeScalar值的value属性,128054,是一个十六进制1F436的十进制表示。其等同于DOG FACE的Unicode标量U+1F436。
Collection Types
Swift提供了三种主要的集合类型 数组,集合和字典,用来存储一组值。数组是有序的值的集合。集合是唯一值的无序集合。字典是键值对的无序集合。
array和dictionary需要明确所存储的类型,不可以插入错误类型的数据,获取数据的时候你也就可以安心知道自己会拿到什么类型的数据~
Array声明为var或者let的时候行为是不一样的(可变or不可变),以及作为参数传入方法也是不一样的。
Arrays
数组可以将相同类型的值存储为一个有序列表。一个数组可以在不同的位置存在多个同样的值。
swift存储数组需要明确类型,这点和OC的NSArray不太一样,OC你可以指定返回类型是id,但是Swift明确要求类型一致,当然你还可以建一个Int数组不一定是object哦~ 但类型安全是swift的base。
Array Type Shorthand Syntax
类型声明Array<SomeType>
或者SomeType[]
,虽然两者结果一样,但是prefer后者的声明方式吼。
Array Literals
可以通过[ value1 , value2 , value3 ]
的方式声明array,如果给出字面量可以同时声明array类型,也可以不声明(会根据给出的字面量推测)。
var shoppingLists = ["Eggs", "Milk"]
shoppingLists.append(2) // compile error
Accessing and Modifying an Array
加元素可以除了append
还可以+=
:
shoppingLists += ["Chocolate Spread", "Cheese", "Butter"]
还可以通过一个范围的下标改一段儿:(可以用2个元素替换原来3个元素,这样数组会变短)
shoppingList[4...6] = ["Bananas", "Apples"]
如果想在中间插入,还可以:
shoppingLists.insert("Maple Syrup", at: 0)
移除可以:
let mapleSyrup = shoppingLists.remove(at: 0)
返回值就是被移除的元素
如果想移除最后一个,可以用:(和OC里面的lastObject类似)
shoppingLists.removeLast()
这样可以省掉去查array count的消耗
Iterating Over an Array
使用for-in循环遍历数组的所有元素:
for item in shoppingList {
print(item)
}
// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas
如果同时需要数组的值和对应的整形索引,使用enumerated()方法。对于数组中的每个元素,enumerated()方法返回一个由整数和元素组成的元组
。整数从0开始计数每次加1,如果你枚举了整个数组,这些整数匹配元素的索引。可以将元组解包为临时的常量或者变量作为遍历的一部分:
for (index, value) in shoppingList.enumerated() {
print("Item \(index + 1): \(value)")
}
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas
Creating and Initializing an Array
使用初始化语法创建某个类型的空数组:
var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
// Prints "someInts is of type [Int] with 0 items."
注意变量someInts的类型根据构造器的类型被推断为[Int]。
此外,如果上下文已经提供了类型信息,例如一个函数的参数或者一个已知类型的变量或者常量,可以使用一个空的数组字面量[]创建一个空数组:
someInts.append(3)
// someInts now contains 1 value of type Int
someInts = []
// someInts is now an empty array, but is still of type [Int]
Swift的数组类型同样提供了一个构造器来创建一个固定大小,默认值均相同的数组。向参数repeating传入一个适当类型的默认值,向参数count传入数组的大小:
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
因为默认值已经提供了类型信息,所以不用声明类型~
使用加号运算符+将两个类型兼容的已知数组相加来创建一个新的数组。新数组的类型通过相加的两个数组的类型来推断:
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
Dictionaries
字典以无序的方式将相同类型的键和相同类型的值构成的关联对象存储在一个集合中。
类似数组的是,同样要声明类型信息,Swift字典类型完整写法为Dictionary<Key, Value>
,Key是可以用来作为字典键的值的类型,Value是字典为那些键所存储的值的类型。
字典的Key类型必须遵循Hashable协议,像集合的值类型一样。(枚举虽然没有值,但默认也是hashable的)
Dictionary Literals
字典也可以以字面量声明[ key1 : value1 , key2 : value2 , key3 : value3 ]
:(类型信息也可忽略)
var airports: Dictionary<String, String> = ["TYO": "Tokyo", "DUB": "Dublin"]
Accessing and Modifying a Dictionary
如果想添加直接赋值key value即可:
airports["LHR"] = "London"
添加后修改也是这样做~
除了下标语法,也可以使用字典的updateValue(_:forKey:)
方法设置或者更新一个特殊键对应的值。像上例的下标一样,如果键不存在,updateValue(_:forKey:)
方法为这个键设置一个新值,反之会更新这个值。与下标不同,当执行完更新后,updateValue(_:forKey:)
方法会返回旧值。这使你可以检查是否执行了更新。
updateValue(_:forKey:)
方法返回字典值类型的可选值。
例如,一个字典存储String值,这个方法返回一个String?类型或者“可选的String”型的值。更新之前值存在的话,这个可选型会包含这个旧值,反之返回nil:
airports.updateValue("Tokyo1", forKey: "TYO")
同样可以使用下标语法来访问字典中一个特殊键对应的值。因为可能请求一个不存在值的键,字典的下标会返回这个字典值类型的可选值。
if let airportName = airports["DUB"] {
print("The name of the airport is \(airportName).")
} else {
print("That airport is not in the airports dictionary.")
}
// Prints "The name of the airport is Dublin Airport."
可以使用下标语法删除一个键值对,方法为对这个键对应的值赋值为nil;同样可以使用removeValue(forKey:)方法删除一个键值对。这个方法在键值对存在的情况下会删除这个键值对并返回删除的值,反之返回nil。
Iterating Over a Dictionary
使用for-in循环遍历字典的键值对。字典的每个元素会被返回为一个(key, value)类型的元组,可以将这个元组的成员解包为临时的常量或者变量作为遍历的一部分:
for (airportCode, airportName) in airports {
print("\(airportCode): \(airportName)")
}
// YYZ: Toronto Pearson
// LHR: London Heathrow
同样可以通过访问字典的keys和values属性来访问一个字典的键或者值的集合:
for airportCode in airports.keys {
print("Airport code: \(airportCode)")
}
// Airport code: YYZ
// Airport code: LHR
for airportName in airports.values {
print("Airport name: \(airportName)")
}
// Airport name: Toronto Pearson
// Airport name: London Heathrow
可以通过keys和values创建array:
let airportNames = Array(airports.values)
Creating an Empty Dictionary
var namesOfIntegers = Dictionary<Int, String>()
var namesOfIntegers = [Int: String]()
Mutability of Collections
用let声明的不可变数组长度是不能再变了哦,不可变的dictionary是不可以改key对应的value的哦(其实和OC是一样的不可变0.0)可以理解为内容固定了
网友评论