Part 2:(Strings and Characters, Collection Types, Control Flow)

来源:互联网 发布:如何理解面向对象编程 编辑:程序博客网 时间:2024/05/16 06:18

3 Strings and Characters



3.4Strings Are Value Types

Swift’s String type is a value type. If you create a new String value, that String value is copied when it is passed to a function or method, or when it is assigned to a constant or variable. In each case, a new copy of the existing String value is created, and the new copy is passed or assigned, not the original version. 

NOTE

This behavior differs from that of NSString in Cocoa. When you create an NSString instance in Cocoa, and pass it to a function or method or assign it to a variable, you are always passing or assigning a reference to the same single NSString. No copying of the string takes place, unless you specifically request it.


swift中,String是值传递的,当它作为函数或方法的参数传递,或赋值给一个常量或变量时,会创建新的副本。传过去的是新的副本。

这与cocoa中得NSString不一样,cocoa中传的是引用


3.5Working with Characters

Alternatively, create a stand-alone Character constant or variable from a single-character string literal by providing a Character type annotation:


  • let yenSign: Character = "¥"


声明字符类型并赋初值,就要表明类型名,不然就变成字符串了


3.6Concatenating Strings and Characters


let a: Character = "!"

var b = "abc"

//b += a //'String' is not identical to 'UInt8'

b.append(a)  //"abc!"


连接字符串和字符要用append方法,不能直接 +=, 也不能 b+a




3.8.2Special Unicode Characters in String Literals

String literals can include the following special Unicode characters:

  • The escaped special characters \0 (null character), \\ (backslash), \t (horizontal tab), \n (line feed), \r (carriage return), \" (double quote) and \' (single quote) 
  • An arbitrary Unicode scalar, written as \u{n}, where n is between one and eight hexadecimal digits

let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"

// "Imagination is more important than knowledge" - Einstein

let dollarSign = "\u{24}"        // $,  Unicode scalar U+0024

let blackHeart = "\u{2665}"      // ♥,  Unicode scalar U+2665

let sparklingHeart = "\u{1F496}" // , Unicode scalar U+1F496

let a = ""  //

部分字符不能显示,所以删掉,请看下图完整版


3.8.3Extended Grapheme Clusters

Every instance of Swift’s Character type represents a single extended grapheme cluster. An extended grapheme cluster is a sequence of one or more Unicode scalars that (when combined) produce a single human-readable character.


有的字符是一系列字符的组成


let eAcute: Character = "\u{E9}"                         // é

let combinedEAcute: Character = "\u{65}\u{301}"          // e followed by ́

// eAcute is é, combinedEAcute is é


let precomposed: Character = "\u{D55C}"                  // 

let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"   // 

// precomposed is , decomposed is 


let enclosedEAcute: Character = "\u{E9}\u{20DD}" //é

// enclosedEAcute is é

let cha1: Character = "\u{E9}"  //é

let cha2: Character = "\u{20DD}"  //一个圈圈

let enclosedEAcute2: Character = "\u{65}\u{301}\u{20dd}"//é

// enclosedEAcute2 is é


let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"  //

// regionalIndicatorForUS is 

部分字符不能显示,所以删掉,请看下图完整版


3.9Counting Characters

countElements函数来获取字符串的字符数

增加字符不一定会增加字符数,原因见3.8.3,如下例:


var word = "cafe"

println("the number of characters in \(word) is \(countElements(word))")

// prints "the number of characters in cafe is 4"


word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301


println("the number of characters in \(word) is \(countElements(word))")

// prints "the number of characters in café is 4"


这里算出来的结果跟NSString的属性length计算结果可能是不一样的,因为NSString是基于16位编码的。要获取16位编码的长度可以访问字符串的utf16Count属性



3.10.1String and Character Equality


Two String values (or two Character values) are considered equal if their extended grapheme clusters are canonically equivalent. Extended grapheme clusters are canonically equivalent if they have the same linguistic meaning and appearance, even if they are composed from different Unicode scalars behind the scenes.


两个字符串相等,如果它们的extended grapheme clusters canonically 相等


let b = ("\u{E9}" ==  "\u{65}\u{301}")  //true





3.11Unicode Representations of Strings



let dogString = "Dog‼ "

for a in dogString{

    println(a)

}


打印

D

o

g



for a in dogString.utf8{

    println(a)

}

打印

68

111

103

226

128

188

240

159

144

182

// D(68) o(111) g(103) ‼(226 128 188) (240 159 144 182)


for a in dogString.utf16{

    println(a)

}


打印

68

111

103

8252

55357

56374

// D(68) o(111) g(103) ‼(8252) (55357 56374)



for a in dogString.unicodeScalars{

    print("\(a)(\(a.value)) ")

}

打印 D(68) o(111) g(103) ‼(8252) (128054)


请看下图完整版



4 Collection Types

4.2Arrays

Swift arrays are specific about the kinds of values they can store. They differ from Objective-C’sNSArray andNSMutableArray classes, which can store any kind of object and do not provide any information about the nature of the objects they return.


swiftarray需要指明可存储类型

ocNSArray不需要指明可存储类型,它可保存任意类型


4.2.1 Array Type Shorthand Syntax

类型声明

Array<SomeType>完整版

[SomeType]简约版


4.2.3 Accessing and Modifying an Array


shoppingList[4...6] = ["Bananas","Apples"]

把原来数组中得3个元素替换成这两个元素。数组的元素个数自动减一


4.2.5 Creating and Initializing an Array

var threeDoubles = [Double](count:3, repeatedValue:0.0)

// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]


4.3Dictionaries

Swift dictionaries are specific about the types of keys and values they can store. They differ from Objective-C’sNSDictionary andNSMutableDictionary classes, which can use any kind of object as their keys and values and do not provide any information about the nature of those objects. In Swift, the type of keys and values that a particular dictionary can store is always made clear, either through an explicit type annotation or through type inference.


dictonaries的key和values需指明类型

oc中得NSDictinary不需要指明类型,它可以是任意类型


4.3.1Dictionary Type Shorthand Syntax

类型声明

Dictionary<Key, Value> 完整版  

[Key: Value] 简约版




4.3.2Dictionary Literals

var airports: [String:String] = ["YYZ":"Toronto Pearson", "DUB":"Dublin"]



4.3.3Accessing and Modifying a Dictionary


//可以这样来增加和修改

airports["LHR"] ="London"

// the airports dictionary now contains 3 items

airports["LHR"] ="London Heathrow"

// the value for "LHR" has been changed to "London Heathrow"


//用这个方法修改可以返回旧的值

The updateValue(forKey:) method returns an optional value of the dictionary’s value type.

iflet oldValue =airports.updateValue("Dublin Airport", forKey:"DUB") {

    println("The old value for DUB was\(oldValue).")

}

// prints "The old value for DUB was Dublin."


//角标返回可选值

a dictionary’s subscript returns an optional value of the dictionary’s value type.

iflet airportName =airports["DUB"] {

    println("The name of the airport is\(airportName).")

}else {

    println("That airport is not in the airports dictionary.")

}

// prints "The name of the airport is Dublin Airport."


//用角标来移除键值对

You can use subscript syntax to remove a key-value pair from a dictionary by assigning a value ofnil for that key:

airports["APL"] ="Apple International"

// "Apple International" is not the real airport for APL, so delete it

airports["APL"] =nil

// APL has now been removed from the dictionary


//用方法来移除键值对,可返回value

Alternatively, remove a key-value pair from a dictionary with the removeValueForKey method. This method removes the key-value pair if it exists and returns the removed value, or returnsnil if no value existed:


iflet removedValue =airports.removeValueForKey("DUB") {

    println("The removed airport's name is\(removedValue).")

}else {

    println("The airports dictionary does not contain a value for DUB.")

}

// prints "The removed airport's name is Dublin Airport."


4.3.4Iterating Over a Dictionary



//遍历字典

for (airportCode, airportName)inairports {

   println("\(airportCode):\(airportName)")

}

// LHR: London Heathrow

// YYZ: Toronto Pearson



for airportCodeinairports.keys {

   println("Airport code:\(airportCode)")

}

// Airport code: LHR

// Airport code: YYZ


for airportNameinairports.values {

   println("Airport name:\(airportName)")

}

// Airport name: London Heathrow

// Airport name: Toronto Pearson


let airportCodes = [String](airports.keys)

// airportCodes is ["LHR", "YYZ"]


let airportNames = [String](airports.values)

// airportNames is ["London Heathrow", "Toronto Pearson"]



4.3.5Creating an Empty Dictionary

var namesOfIntegers = [Int:String]()

// namesOfIntegers is an empty [Int: String] dictionary


namesOfIntegers[16] ="sixteen"

// namesOfIntegers now contains 1 key-value pair

namesOfIntegers = [:]

// namesOfIntegers is once again an empty dictionary of type [Int: String]


4.3.6Hash Values for Dictionary Key Types

字典中得键必须可进行hash计算,且如果两个数值相等,其hash值也必须相等


All of Swift’s basic types (such as String, Int, Double, and Bool) are hashable by default, and all of these types can be used as the keys of a dictionary. Enumeration member values without associated values (as described inEnumerations) are also hashable by default.





5 Control Flow

5.1.1 For-In


for indexin1...5 {

   println("\(index) times 5 is\(index *5)")

}


// 1 times 5 is 5

// 2 times 5 is 10

// 3 times 5 is 15

// 4 times 5 is 20

// 5 times 5 is 25


/*

If you don’t need each value from the range, you can ignore the values by using an underscore in place of a variable name:

*/

let base =3

let power =10

var answer =1

for_in 1...power {

    answer *= base

}

println("\(base) to the power of\(power) is\(answer)")

// prints "3 to the power of 10 is 59049"



5.3Conditional Statements


5.3.2Switch

let someCharacter:Character ="e"

switch someCharacter {

case "a","e","i", "o", "u":

    println("\(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":

    println("\(someCharacter) is a consonant")

default:

    println("\(someCharacter) is not a vowel or a consonant")

}

// prints "e is a vowel"


5.3.2.1No Implicit Fallthrough


In contrast with switch statements in C and Objective-C, switch statements in Swift do not fall through the bottom of each case and into the next one by default. Instead, the entireswitch statement finishes its execution as soon as the first matchingswitch case is completed, without requiring an explicitbreak statement. This makes theswitch statement safer and easier to use than in C, and avoids executing more than oneswitch case by mistake.


默认不穿透后面的分支,即当一个分支执行完成,switch语句就结束了,不需要显示break.



let anotherCharacter:Character ="a"

switch anotherCharacter {

case "a"://'case' label in a 'switch' should have at least one executable statement

case "A":

    println("The letter A")

default:

    println("Not the letter A")

}

// this will report a compile-time error


case分支中必须要有语句,上面的写法编译错误


NOTE

To opt in to fallthrough behavior for a particularswitch case, use thefallthrough keyword, as described inFallthrough.


如果确实想穿透分支,使用fallthrough


5.3.2.2Range Matching


let count = 3_000_000_000_000

let countedThings ="stars in the Milky Way"

var naturalCount:String

switch count {

case 0:

    naturalCount ="no"

case1...3:

    naturalCount ="a few"

case4...9:

    naturalCount ="several"

case10...99:

    naturalCount ="tens of"

case 100...999:

    naturalCount ="hundreds of"

case 1000...999_999:

    naturalCount ="thousands of"

default:

    naturalCount ="millions and millions of"

}

println("There are\(naturalCount)\(countedThings).")

// prints "There are millions and millions of stars in the Milky Way."


case分支条件可以是一个范围


5.3.2.3Tuples


You can use tuples to test multiple values in the same switch statement. Each element of the tuple can be tested against a different value or range of values. Alternatively, use the underscore (_) identifier to match any possible value.



let somePoint = (1,1)

switch somePoint {

case (0,0):

    println("(0, 0) is at the origin")

case (_,0):

    println("(\(somePoint.0), 0) is on the x-axis")

case (0,_):

    println("(0,\(somePoint.1)) is on the y-axis")

case (-2...2, -2...2):

    println("(\(somePoint.0),\(somePoint.1)) is inside the box")

default:

    println("(\(somePoint.0),\(somePoint.1)) is outside of the box")

}

// prints "(1, 1) is inside the box"



5.3.2.4Value Bindings


A switch case can bind the value or values it matches to temporary constants or variables, for use in the body of the case. This is known asvalue binding, because the values are “bound” to temporary constants or variables within the case’s body.


let anotherPoint = (2,0)

switch anotherPoint {

case (let x,0):

    println("on the x-axis with an x value of\(x)")

case (0,let y):

    println("on the y-axis with a y value of\(y)")

caselet (x, y):

    println("somewhere else at (\(x),\(y))")

}

// prints "on the x-axis with an x value of 2"


5.3.2.5Where


A switch case can use awhere clause to check for additional conditions.


let yetAnotherPoint = (1, -1)

switch yetAnotherPoint {

caselet (x, y)where x == y:

    println("(\(x),\(y)) is on the line x == y")

caselet (x, y)where x == -y:

    println("(\(x),\(y)) is on the line x == -y")

caselet (x, y):

    println("(\(x),\(y)) is just some arbitrary point")

}

// prints "(1, -1) is on the line x == -y"


5.4Control Transfer Statements


Swift has four control transfer statements:

  • continue 
  • break 
  • fallthrough 
  • return

5.4.3Fallthrough


If you really need C-style fallthrough behavior, you can opt in to this behavior on a case-by-case basis with thefallthrough keyword. The example below usesfallthrough to create a textual description of a number:


let integerToDescribe =5

var description ="The number\(integerToDescribe) is"

switch integerToDescribe {

case2,3, 5, 7, 11,13,17, 19:

    description +=" a prime number, and also"

    fallthrough

default:

    description +=" an integer."

}

println(description)

// prints "The number 5 is a prime number, and also an integer."


5.4.4Labeled Statements


循环语句,选择语句是可以穿插进行的,这是在进行break时,可能就不太清楚结束的是哪个语句。

为了使这种复杂的情况表达得更加清晰,可使用标签声明


var i =0

Loop:whilei < 10{

   switchi{

   case1,3,5,7:

       println("\(i)是奇数")

   case0,2,4,6:

       println("\(i)是偶数")

   case8:

       i =1

       continue

   case9:

       break

//        break Loop //如果增加标签,则最后当前i=11”不会打印出来

    default:

       println("\(i)这个...")

    }

   i +=2

   println("当前i=\(i)")

}


打印:

0是偶数

当前i=2

2是偶数

当前i=4

4是偶数

当前i=6

6是偶数

当前i=8

1是奇数

当前i=3

3是奇数

当前i=5

5是奇数

当前i=7

7是奇数

当前i=9

当前i=11




0 0