swift基础知识学习
用let来声明常量,用var来声明变量
声明变量:
var x = 0.0, y = 0.0, z = 0.0
var welcomeMessage: String
常量和变量的命名
你可以用任何你喜欢的字符作为常量和变量名,包括 Unicode 字符
常量与变量名不能包含数学符号,箭头,保留的(或者非法的)Unicode 码位,连线与制表符。也不能以数字开头,但是可以在常量与变量名的其他地方包含数字。
一旦你将常量或者变量声明为确定的类型,你就不能使用相同的名字再次进行声明,或者改变其存储的值的类型。同时,你也不能将常量与变量进行互转。
注意:如果你需要使用与Swift保留关键字相同的名称作为常量或者变量名,你可以使用反引号(`)将关键字包围的方式将其作为名字使用。无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择
println 输出的内容会在最后换行 (另一种函数叫print,唯一区别是在输出内容最后不会换行。)
println函数可以输出更复杂的信息。这些信息可以包含当前常量和变量的值。
Double表示64位浮点数
Float表示32位浮点数
Swift 是一个类型安全(type safe )的语言,
Swift 会使用类型推测(type inference)来选择合适的类型,编译器可以在编译代码的时候自动推测出表达式的类型。原理很简单,只要检查你赋的值即可。
数值型字面量
整数字面量可以被写作:- 一个十进制数,没有前缀
- 一个二进制数,前缀是0b
- 一个八进制数,前缀是0o
- 一个十六进制数,前缀是0x
如果一个十进制数的指数为exp,那这个数相当于基数和$10^{exp}$的乘积:
- 1.25e2 表示 $1.25 × 10^{2}$,等于 125.0。
- 1.25e-2 表示 $1.25 × 10^{-2}$,等于 0.0125。
如果一个十六进制数的指数为exp,那这个数相当于基数和$2^{exp}$的乘积:
- 0xFp2 表示 $15 × 2^{2}$,等于 60.0。
- 0xFp-2 表示 $15 × 2^{-2}$,等于 3.75。
数值类字面量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字面量:
let paddedDouble = 000123.456 let oneMillion = 1_000_000 let justOverOneMillion = 1_000_000.000_000_1
简单类型转换
let twoThousand: UInt16 = 2_000 let one: UInt8 = 1 let twoThousandAndOne = twoThousand + UInt16(one)
类型别名
typealias MyType = UInt16
var myMinValue : MyType = MyType.min
var myMaxValue : MyType = MyType.max
元组
//声明方式1
let http404Error = (404, "Not Found") // http404Error 的类型是 (Int, String),值是 (404, "Not Found")
//分解元祖取值
let (statusCode,statusMsg) = http404Error
println("code:\(statusCode)");
println(statusMsg)
//取部分值
let (justNeedCode,_) = http404Error
println("justNeedCode:\(justNeedCode)")
//通过下标访问
println("\(http404Error.0) \(http404Error.1)")
//声明方式2
let http200Status = (statusCode: 200, description: "OK")
println("\(http200Status.statusCode) \(http200Status.description)")
let http404Error = (404, "Not Found") // http404Error 的类型是 (Int, String),值是 (404, "Not Found")
//分解元祖取值
let (statusCode,statusMsg) = http404Error
println("code:\(statusCode)");
println(statusMsg)
//取部分值
let (justNeedCode,_) = http404Error
println("justNeedCode:\(justNeedCode)")
//通过下标访问
println("\(http404Error.0) \(http404Error.1)")
//声明方式2
let http200Status = (statusCode: 200, description: "OK")
println("\(http200Status.statusCode) \(http200Status.description)")
强制解析
let possibleNumber = "123" //"123a"
let convertedNumber = possibleNumber.toInt()
// convertedNumber 被推测为类型 "Int?", 或者类型 "optional Int"
//强制解析
if (convertedNumber != nil) {
println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
这个惊叹号表示“我知道这个可选有值,请使用它。
注意:Swift 的nil和 Objective-C 中的nil并不一样。在 Objective-C 中,nil是一个指向不存在对象的指针。在 Swift 中,nil不是指针——它是一个确定的值,用来表示值缺失。任何类型的可选都可以被设置为nil,不只是对象类型
隐式解析可选
var possibleString: String? = "An optional string."
println(possibleString!) // 需要惊叹号来获取值
// 输出 "An optional string."
var assumedString : String! = "An implicitly unwrapped optional string."
println(assumedString) // 不需要感叹号
// 输出 "An implicitly unwrapped optional string."
//possibleString = nil
//assumedString = nil
if (assumedString != nil) {
println(assumedString)
}
// 输出 "An implicitly unwrapped optional string."
if let definiteString = assumedString {
println(definiteString)
}
println(possibleString!) // 需要惊叹号来获取值
// 输出 "An optional string."
var assumedString : String! = "An implicitly unwrapped optional string."
println(assumedString) // 不需要感叹号
// 输出 "An implicitly unwrapped optional string."
//possibleString = nil
//assumedString = nil
if (assumedString != nil) {
println(assumedString)
}
// 输出 "An implicitly unwrapped optional string."
if let definiteString = assumedString {
println(definiteString)
}
注意:如果一个变量之后可能变成nil的话请不要使用隐式解析可选。如果你需要在变量的生命周期中判断是否是nil的话,请使用普通可选类型。
断言
如果条件判断为true,代码运行会继续进行;如果条件判断为false,代码运行停止,你的应用被终止。
let age = -3 assert(age >= 0, "A person's age cannot be less than zero") // 因为 age < 0,所以断言会触发
数值运算
加法运算符也用于String的拼接:
"hello, " + "world" // 等于 "hello, world"
区间运算符
for index in 1...5 {
println("\(index) * 5 = \(index * 5)")
}
println("\(index) * 5 = \(index * 5)")
}
半闭区间
半闭区间(a..b)定义一个从a到b但不包括b的区间。 之所以称为半闭区间,是因为该区间包含第一个值而不包括最后的值。
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
println("第 \(i + 1) 个人叫 \(names[i])")
} // 第 1 个人叫 Anna // 第 2 个人叫 Alex // 第 3 个人叫 Brian // 第 4 个人叫 Jack
字符串字面量
字符串字面量可以包含以下特殊字符:
- 转移特殊字符 \0 (空字符)、\\(反斜线)、\t (水平制表符)、\n (换行符)、\r (回车符)、\" (双引号)、\' (单引号)。
- 单字节 Unicode 标量,写成 \xnn,其中 nn 为两位十六进制数。
- 双字节 Unicode 标量,写成 \unnnn,其中 nnnn 为四位十六进制数。
- 四字节 Unicode 标量,写成 \Unnnnnnnn,其中 nnnnnnnn 为八位十六进制数。
初始化空字符串
var emptyString = "" // 空字符串字面量 var anotherEmptyString = String() // 初始化 String 实例 // 两个字符串均为空并等价。
字符串可变性
var variableString = "Horse" variableString += " and carriage" // variableString 现在为 "Horse and carriage" let constantString = "Highlander" constantString += " and another Highlander" // 这会报告一个编译错误(compile-time error) - 常量不可以被修改。
注意:在 Objective-C 和 Cocoa 中,您通过选择两个不同的类( NSString 和 NSMutableString )来指定该字符串是否可以被修改,Swift中的字符串是否可以修改仅通过定义的是变量还是常量来决定,实现了多种类型可变性操作的统一。
字符串是值类型
任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值。
注意:其 Cocoa 中的 NSString 不同,当您在 Cocoa 中创建了一个 NSString 实例,并将其传递给一个函数/方法,或者赋值给一个变量,您永远都是传递或赋值同一个 NSString 实例的一个引用。除非您特别要求其进行值拷贝,否则字符串不会进行赋值新副本操作。
注意:其 Cocoa 中的 NSString 不同,当您在 Cocoa 中创建了一个 NSString 实例,并将其传递给一个函数/方法,或者赋值给一个变量,您永远都是传递或赋值同一个 NSString 实例的一个引用。除非您特别要求其进行值拷贝,否则字符串不会进行赋值新副本操作。
使用字符(Characters)
遍历字符串
for character in "Dog!" {
println(character)
}
println(character)
}
计算长度
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"println("unusualMenagerie has \(countElements(unusualMenagerie)) characters\(unusualMenagerie.utf16Count)"// prints "unusualMenagerie has 40 characters 44"
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"println("unusualMenagerie has \(countElements(unusualMenagerie)) characters\(unusualMenagerie.utf16Count)"// prints "unusualMenagerie has 40 characters 44"
另外需要注意的是通过 countElements 返回的字符数量并不总是与包含相同字符的 NSString 的 length 属性相同。NSString 的 length 属性是基于利用 UTF-16 表示的十六位代码单元数字,而不是基于 Unicode 字符。为了解决这个问题,NSString 的 length 属性在被 Swift的 String 访问时会成为 utf16count。
比较字符串
如果两个字符串以同一顺序包含完全相同的字符,则认为两者字符串相等
数组(Array)
var shoppingList: String[] = ["Eggs", "Milk"] // shoppingList 用两个元素完成初始化
等价于 得益于Swift的类型推断
var shoppingList = ["Eggs", "Milk"]
使用Boolean型的isEmpty属性,可以快速检查count属性是否为0
let bookList : [String] = ["悲惨世界","我的处女地"]
println(bookList.count)
var bookList2 = ["悲惨世界","我的处女地"]
bookList2.append("我的新书")
bookList2 += ["Chocolate Spread", "Cheese", "Butter"]
//无效
//bookList2 += "Chocolate Spread"
//遍历数组
for book in bookList2
{
print(book)
}
print(bookList2[0])
print(bookList2[1...3])
print(bookList2[1..<3])
//指定位置添加
bookList2.insert("第一本书", atIndex: 0)
//指定位置删除
bookList2.removeAtIndex(0)
bookList2.removeLast()
//遍历数组
//enumerate方法对每个元素都会返回一个由索引值及对应元素值组成的元组
for(index,value) in enumerate(bookList2)
{
println("\(index) : \(value)")
//指定位置添加
bookList2.insert("第一本书", atIndex: 0)
//指定位置删除
bookList2.removeAtIndex(0)
bookList2.removeLast()
//遍历数组
//enumerate方法对每个元素都会返回一个由索引值及对应元素值组成的元组
for(index,value) in enumerate(bookList2)
{
println("\(index) : \(value)")
}
//初始化int数组
var someInts = [Int]()
someInts += [1,2,3,4,5]
//错误 必须是int类型
//someInts.append("2")
//生成若干个重复元素组成的数组的初始化函数
var threeDoubles = [Double](count: 3, repeatedValue: 1.0)
var someInts = [Int]()
someInts += [1,2,3,4,5]
//错误 必须是int类型
//someInts.append("2")
//生成若干个重复元素组成的数组的初始化函数
var threeDoubles = [Double](count: 3, repeatedValue: 1.0)
// threeDoubles类型为Double[],值为[1.0, 1.0, 1.0]
//根据Swift的类型推断,在使用这个初始化函数的时候,不必精确说明该数组的类型,因为这能从默认值中推断出
var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)
var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)
anotherThreeDoubles.append(333)
字典(Dictionary)
//[key 1: value 1, key 2: value 2, key 3: value 3]
var airports: Dictionary<String, String> = ["TYO": "Tokyo", "DUB": "Dublin"]
var airports2 = ["TYO": "Tokyo", "DUB": "Dublin"]
//airports airports2等价
//新建
airports["LHR"] = "London"
//更新1
airports["LHR"] = "London2"
//更新2 updateValue(forKey:)函数在键不存在的时候就设置一个新值,在键存在的时候就更新该值
//updateValue(forKey:)函数在更新一个值之后,会返回原来的老值,这让你能够检测是否发生了值的更新。
var returnOldValue = airports.updateValue("china", forKey: "LHR")
println("updateValue return Old Value \(returnOldValue)")
//updateValue(forKey:)函数返回一个值的类型的可选值。例如一个值类型为String的字典,该函数返回值的类型为String?。如果更新前该键的值存在,函数返回值就是该键更新前的值,如果不存在,函数返回值就是nil:
//删除key
//从字典中删除键值对也可以使用removeValueForKey函数。如果该键值对存在,该函数就返回本删掉的值,如果不存在,就返回nil:
airports.removeValueForKey("LHR")
//遍历字典
for dic in airports{
println(dic)
}
if let airportName = airports["DUB"] {
println("The name of the airport is \(airportName).")
} else {
println("That airport is not in the airports dictionary.")
}
// 输出 "The name of the airport is Dublin International."
airports["APL"] = "Apple International"
// "Apple International" 不是APL的机场,所以要删除它 airports["APL"] = nil
// APL键值对已经从字典中删除了
airports["APL"]=nil
//遍历字典
for dic in airports{
println(dic)
}
var airports: Dictionary<String, String> = ["TYO": "Tokyo", "DUB": "Dublin"]
var airports2 = ["TYO": "Tokyo", "DUB": "Dublin"]
//airports airports2等价
//新建
airports["LHR"] = "London"
//更新1
airports["LHR"] = "London2"
//更新2 updateValue(forKey:)函数在键不存在的时候就设置一个新值,在键存在的时候就更新该值
//updateValue(forKey:)函数在更新一个值之后,会返回原来的老值,这让你能够检测是否发生了值的更新。
var returnOldValue = airports.updateValue("china", forKey: "LHR")
println("updateValue return Old Value \(returnOldValue)")
//updateValue(forKey:)函数返回一个值的类型的可选值。例如一个值类型为String的字典,该函数返回值的类型为String?。如果更新前该键的值存在,函数返回值就是该键更新前的值,如果不存在,函数返回值就是nil:
//删除key
//从字典中删除键值对也可以使用removeValueForKey函数。如果该键值对存在,该函数就返回本删掉的值,如果不存在,就返回nil:
airports.removeValueForKey("LHR")
//遍历字典
for dic in airports{
println(dic)
}
if let airportName = airports["DUB"] {
println("The name of the airport is \(airportName).")
} else {
println("That airport is not in the airports dictionary.")
}
// 输出 "The name of the airport is Dublin International."
airports["APL"] = "Apple International"
// "Apple International" 不是APL的机场,所以要删除它 airports["APL"] = nil
// APL键值对已经从字典中删除了
airports["APL"]=nil
//遍历字典
for dic in airports{
println(dic)
}
//字典的迭代访问
for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}
//生成一个空字典
var namesOfIntegers = Dictionary<Int, String>()
namesOfIntegers[16] = "sixteen"
namesOfIntegers = [:]
// namesOfIntegers又成为一个类型为Int,String的空字典
for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}
//生成一个空字典
var namesOfIntegers = Dictionary<Int, String>()
namesOfIntegers[16] = "sixteen"
namesOfIntegers = [:]
// namesOfIntegers又成为一个类型为Int,String的空字典
注意: 实际上,Swift的数组和字典类型是通过泛型集合实现的。要获得关于泛型类型和集合的更多资料,请查看Generics。
For Loops - For循环
//如果不需要范围的值,可以用下划线替代变量名来忽略这些值:
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"
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
println("\(animalName)s have \(legCount) legs")
}
var index: Int
for index = 0; index < 3; ++index {
println("index is \(index)")
}
println("The loop statements were executed \(index) times")
// prints "The loop statements were executed 3 times"
//最后一次执行增量表达式调用了++index,把index设为3
//如果有多个匹配对象的,可以用逗号隔开
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"
//Range Matching - 范围匹配
let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: String
switch count {
case 0:
naturalCount = "no"
case 1...3:
naturalCount = "a few"
case 4...9:
naturalCount = "several"
case 10...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."
Tuples 元组
你可以使用元组在相同的switch语句中测试多个值。每一个元组中的元素都可以试着和范围中不同的值进行匹配。另外,用下划线(_)标示符来匹配任意可能的值。
//使用一个点坐标(x,y),用元组型(Int, Int)来表示,可以在下面的图中分类出来:
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"
Value Bindings 值绑定
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)")
case let (x, y):
println("somewhere else at (\(x), \(y))")
}
// prints "on the x-axis with an x value of 2
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)")
case let (x, y):
println("somewhere else at (\(x), \(y))")
}
// prints "on the x-axis with an x value of 2
Control Transfer Statements - 控制转移语句
Swift有四个句子:
- continue
- break
- fallthrough
- return
fallthrough关键字不检查case里的条件,会直接掉入下一个case。fallthrough简单的让代码执行到下一个case(或default)的代码块中,和标准C语言的特性一样。
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."
}
println(description)
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."
}
println(description)
// prints "The number 5 is a prime number, and also an integer."