標籤:
基礎運算子
Swift的大部分運算子和C及OC相同,也分一元二元多元的,這裡只記錄一些Swift特有的性質或寫法。
賦值運算子( = )
在等號右邊是一個有多個值的元組時,它的成員值可以分解並同時分別賦值給常量或者變數:
let (x, y) = (1, 2)// x is equal to 1, and y is equal to 2
和C、OC不同的是,賦值運算子本身並不傳回值,因此如下寫法是錯誤的:
if x = y { // this is not valid, because x = y does not return a value}
這主要是為了防止其和相等運算子混淆。
取餘運算子(%)
取餘運算在有些語言中也被稱為模數,不過在Swift中不能這樣稱,因為負數的時候,餘數也是帶符號的,比如 -9 % 4 = -1,並且,第二個運算元的符號是被忽略的,也就是說,
a % b 和 a % -b總是返回相同的值。
與C和OC中的取餘運算子不同,Swift中的取餘也可以用於浮點數:8 % 2.5 = 0.5
複合賦值運算子
比如a+=2意味著a=a+2,不過複合賦值運算子本身並不傳回值,因此let b = a += 2 是錯誤的。
Nil合并運算子
nil合并運算子(a ?? b)在可選項a有值的時候展開a,如果a沒有值,就返回b的值。a必須是一個optional值,並且b和a儲存的值應該是統一類型。它的意思就是
(a != nil) ? a! : b //這裡第二個!是用來強制展開optional值的
nil合并運算子是一種優雅的寫法,可讀性也更高,並且,如果a有值,那麼b將不會參與運算。
範圍運算子
Swift有兩個範圍運算子,"..."和"..<",a...b表示從a到b並且包含a和b的範圍,a..<b表示從a到b但不包含b的範圍,此時如果a=b,則範圍為空白,當然,這兩個都要求a不能大於b。
字串和字元
Swift的字串和字元文法很簡單,也可以直接用+號串連多個字串,並且Swift的字串提供一種快速、符合Unicode編碼的文本處理工具。
並且,字串中可以插入常量、變數、字面量、運算式。
Swift的string類型和Foundation架構中的NSString是相同的,如果是基於Cocoa的Foundation架構開發,那麼所有NSString的API都可以用在Swift的String上。
字串字面量
字串字面量是指用雙引號包圍起來的定義好的字元序列。比如:let someString = "Some string literal value”。此時編譯器會降someString的類型設定為String,因為它是用一個字串字面量被初始化的。
字串字面量可以包含一些特殊轉義符號:
\0 (null), \\ (反斜線), \t (水平tab), \n (分行符號), \r (斷行符號), \" (雙引號) and \‘ (單引號)
也可以包含直接的Unicode純量字元(Unicode scalar),Unicode scalar是指在某個指定範圍內的任意Unicode代碼點,它代表一個Unicode字元。在字串中包含Unicode scalar時,用u開頭,加上大括弧包圍的代碼點數字。
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"// "Imagination is more important than knowledge" - Einsteinlet dollarSign = "\u{24}" // $, Unicode scalar U+0024let blackHeart = "\u{2665}" // ♥, Unicode scalar U+2665let sparklingHeart = "\u{1F496}" // ??, Unicode scalar U+1F496
建立字串,可以用字串字面量建立,也可以用初始化方法:String() 。
與OC不同的是,Swift中的字串如果是被賦給變數,那麼它是可以被修改的。OC中,需要選擇NSString和NSMutableString兩個類來確定該字串是否能被修改。
Swift中String是實值型別(value type)的,實值型別是指當它被賦給常量或者變數,或者被傳遞給函數的時候,它的值會被拷貝出來進行賦予和傳遞操作,而不是原始的那個。這一點和OC是不一樣的,在OC中,你建立一個NSString的執行個體,那麼你在賦值和傳遞的時候,都是用的一個指向該NSString的引用。沒有發生拷貝操作。
Swift之所以要這樣改變,是為了減少開發人員難度,比如,當你的方法接收到某個String的時候,你可以確信這個String就是完全被你控制的,不用擔心別的地方會修改它,因為它不是引用,而是拷貝出來的值。不過編譯器其實並不是每次都拷貝了值的,它只是在需要的時候做了這個操作,這樣可以減少很多效能開支。
字元
字串就是一些列有序排列的字元集合。可以對字串用for in來遍曆其中的字元。
for character in "Dog!??" { println(character)}// D// o// g// !// ??
字串也可以通過一個字元數組來建立:
let catCharacters: [Character] = ["C", "a", "t", "!", "??"]let catString = String(catCharacters)println(catString)// prints "Cat!??”
注意:不能將字串或者字元追加(append)到一個已經定義的字元類型變數(Character)後面,因為字元類型是單個字元。
字串插值(String Interpolation)
Swift的字串可以混合插入很多其他東西比如常量、變數、運算式、字面量等等,用反斜線和括弧來實現這種插入,這個特性非常實用。
let multiplier = 3let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"// message is "3 times 2.5 is 7.5”
注意:括弧內部的運算式不能包含未轉義的雙引號、反斜線,也不能包含斷行符號、分行符號。
擴充字元簇(Extended Grapheme Clusters)
Grapheme是指某種自然語言中的最小單元,它並不一定有實際意義,但是它們組合成這種語言的單個字元。Swift語言的每個字元(Character)都是一個獨立的擴充字元簇,一個擴充字元簇就是由一個或多個Unicode scalar(Unicode純量)的有序排列從而組合成可讀的字元。
比如:字母é可以是一個單獨的Unicode scalar:U+00E9,也可以是多個純量的組合:U+0065U+0301 (其中U+0065就是字母e)。在Swift中,這兩種情況都認為是一個字元,因此擷取字串長度的時候(用全域函數count()),返回的值是相同的,這意味著字串的改變並不一定意味著其長度發生變化。
注意區分這和OC中NSString的length的區別,NSString的長度是基於字串在UTF-16編碼錶示時其中包含的16位的單元的個數,而不是Unicode擴充字元簇的數目。為了反映這個區別,NSString的length屬性在Swift中用utf16Count函數來代替。
字串的API
每個String都有關聯的索引類型(index type),它標識字串中字元所在的位置,用具體的index來擷取String中位於該位置的字元。startIndex和endIndex會返回字串初始和結束位置。
一個String的某個索引類型值可以通過predecessor()或successor()擷取與它相鄰的前面或後面的索引值。任何索引值都可以通過其他索引值經過一系列操作得到,或者通過全域函數advance(start:n:),嘗試擷取String範圍之外的索引會觸發執行階段錯誤。
let greeting = "Guten Tag"// prints "greeting: String = "Guten Tag""println(greeting.startIndex)// 0println(greeting.endIndex)// 9greeting[greeting.startIndex.successor()]// ugreeting[greeting.endIndex.predecessor()]// glet index = advance(greeting.startIndex, 7)greeting[index]// agreeting.endIndex.successor() // fatal error: can not increment endIndex
indicies(_:)可以建立一個字串中所有單個字元的索引範圍
for index in indices(greeting) { print("\(greeting[index]) ")}// prints "G u t e n T a g”
insert(_:atIndex:)用於向字串特定索引位置插入一個字元:
var welcome = "hello"welcome.insert("!", atIndex: welcome.endIndex)println(welcome)// prints "hello!”
splice(_:atIndex:)用於向字串特定索引位置插入一個字串:
welcome.splice(" there", atIndex: welcome.endIndex.predecessor())println(welcome)// prints "hello there!”
removeAtIndex(_:)用於刪除字串特定索引位置的一個字元:
welcome.removeAtIndex(welcome.endIndex.predecessor())// !println(welcome)// prints "hello there”
removeRange(_:)用於刪除字串特定範圍的子串:
let range = advance(welcome.endIndex, -6)..<welcome.endIndexwelcome.removeRange(range)println(welcome)// prints "hello”
字串比較直接用 ==和 != 。
當字串的擴充字元簇標準地(canonically)相等時(canonically相等是指擴充字元簇是指它們具備相同的語言意義及外觀,而不管它們的Unicode純量組成),就判斷它們相等。
// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTElet eAcuteQuestion = "Voulez-vous un caf\u{E9}?" // "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENTlet combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?" if eAcuteQuestion == combinedEAcuteQuestion { println("These two strings are considered equal")}// prints "These two strings are considered equal”
hasPrefix(_:)和hasSuffix(_:) 用來判斷字串是否含有特定的首碼或尾碼。它們返回布爾值。
字串的Unicode表示
當把一個Unicode編碼的字串寫入一個文字檔或者其他儲存區的時候,字串中的Unicode scalars會以各種基於Unicode的編碼格式進行編碼。比如UTF-8、UTF-16、UTF-32,可以通過String的屬性擷取它在不同編碼時的表示:
utf8屬性擷取UTF-8編碼格式時的碼元集合;
utf16屬性擷取UTF-16編碼格式時的碼元集合;
unicodeScalars屬性擷取UTF-32編碼格式時的碼元集合;
let dogString = "Dog???"for codeUnit in dogString.utf8 { print("\(codeUnit) ")}print("\n")// 68 111 103 226 128 188 240 159 144 182for codeUnit in dogString.utf16 { print("\(codeUnit) ")}print("\n")// 68 111 103 8252 55357 56374for scalar in dogString.unicodeScalars { print("\(scalar.value) ")}print("\n")// 68 111 103 8252 128054
for scalar in dogString.unicodeScalars {
println("\(scalar) ")
}
// D
// o
// g
// ?
// ??
這篇就到這裡,下次開始介紹集合類型。
Swift學習筆記五