Swift学习笔记五

基础运算符

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" - 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

 

创建字符串,可以用字符串字面量创建,也可以用初始化方法: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 = 3
let 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)
// 0
println(greeting.endIndex)
// 9
greeting[greeting.startIndex.successor()]
// u
greeting[greeting.endIndex.predecessor()]
// g
let index = advance(greeting.startIndex, 7)
greeting[index]
// a
greeting.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.endIndex
welcome.removeRange(range)
println(welcome)
// prints "hello”

字符串比较直接用 ==和 != 。

当字符串的扩展字元簇标准地(canonically)相等时(canonically相等是指扩展字元簇是指它们具备相同的语言意义及外观,而不管它们的Unicode纯量组成),就判断它们相等。

// "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 {
    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 182

for codeUnit in dogString.utf16 {
    print("\(codeUnit) ")
}
print("\n")
// 68 111 103 8252 55357 56374

for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ")
}
print("\n")
// 68 111 103 8252 128054

 for scalar in dogString.unicodeScalars {
   println("\(scalar) ")
 }
 // D
 // o
 // g
 // ‼
 // 🐶

这篇就到这里,下次开始介绍集合类型。

posted @ 2015-06-05 18:16  Dson  阅读(1145)  评论(0编辑  收藏  举报