swift基础01

1.Swift 基础类型
Swift 包含了 CObjective-C上所有基础数据类型,Int表示整型值; DoubleFloat 表示浮点型值; Bool是布尔型值;String 是文本型数据。 Swift 还提供了三个基本的集合类型,ArraySetDictionarySwift 还增加了Objective-C中没有的高阶数据类型比如元组(Tuple)。Swift 还增加了可选(Optional)类型,用于处理值缺失的情况。可选类型比 Objective-C 中的 nil 指针更加安全也更具表现力。

2.常量和变量

常量和变量必须在使用前声明,用let来声明常量,用var来声明变量。

let a = 10
var b = 11
var x = 0.0, y = 0.0, z = 0.0

当你声明常量或者变量的时候可以加上类型标注

var str: String

str 变量添加了类型标注,表示这个变量可以存储 String类型的值:

可以在一行中定义多个同样类型的变量,用逗号分割,并在最后一个变量名之后添加类型标注:
var red, green, blue: Double

3.类型安全类型推断

Swift 是一个类型安全(ype safe)的语言.类型安全的语言可以让你清楚地知道代码要处理的值的类型。 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查.由于类型推断,大部分工作时候声明变量或常量的时候并不需要你自己来完成。
当推断浮点数的类型时,Swift 总是会选择Double而不是Float

4.数值型字面量

一个十进制数,没有前缀
一个二进制数,前缀是0b
一个八进制数,前缀是0o oc或者c是 0
一个十六进制数,前缀是0x

数值类字面量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字面量:

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)

let integerPi = Int(pi)

当用这种方式来初始化一个新的整数值时,浮点值会被截断。也就是说 3.895 会变成 3-10.9会变成 -10

如果在需要使用Bool类型的地方使用了非布尔值,Swift 的类型安全机制会报错。

let i = 1
if i {
    // 这个例子不会通过编译,会报错
}

let i = 1
if i == 1 {
    // 这个例子会编译成功
}

*注意:IntInt8的区别

5.元组

元组(tuples)把多个值组合成一个复合值。元组内的值可以是任意类型,并不要求是相同类型。

let http404Error = (404, "Not Found")
// http404Error 的类型是 (Int, String),值是 (404, "Not Found")

可以将一个元组的内容分解(decompose)成单独的常量和变量,然后你就可以正常使用它们

let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// 输出 "The status code is 404"
print("The status message is \(statusMessage)")
// 输出 "The status message is Not Found"

只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_)标记:

let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// 输出 "The status code is 404"

可以通过下标来访问元组中的单个元素,下标从零开始:

print("The status code is \(http404Error.0)")
// 输出 "The status code is 404"
print("The status message is \(http404Error.1)")
// 输出 "The status message is Not Found"

键值

let http200Status = (statusCode: 200, description: "OK")
print("The status code is \(http200Status.statusCode)")
// 输出 "The status code is 200"
print("The status message is \(http200Status.description)")
// 输出 "The status message is OK"

*注意:元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。

6.nil

CObjective-C中并没有可选类型这个概念。最接近的是Objective-C中的一个特性,一个方法要不返回一个对象要不返回nilnil表示“缺少一个合法的对象”。这只对对象起作用——对于结构体,基本的 C 类型或者枚举类型不起作用。对于这些类型,Objective-C 方法一般会返回一个特殊值(比如NSNotFound)来暗示值缺失。Swift可选类型可以让你暗示任意类型值缺失,并不需要一个特殊值。

如果你声明一个可选常量或者变量但是没有赋值,它们会自动被设置为 nil

var surveyAnswer: String?
// surveyAnswer 被自动设置为 nil

7.可选类型

使用可选类型(optionals)来处理值可能缺失的情况。
一个可选的 Int被写作Int?而不是Int。问号暗示包含的值是可选类型,也就是说可能包含 Int 值也可能不包含值。

使用 ! 来获取一个不存在的可选值会导致运行时错误。使用!强制解析值之前,一定要确定可选包含一个非nil的值。

8.可选绑定

使用可选绑定(optional binding)来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。

可选绑定可以用在ifwhile 语句中,这条语句不仅可以用来判断可选类型中是否有值,同时可以将可选类型中的值赋给一个常量或者变量。

if let constantName = someOptional {
    statements
}

理解:
“如果 Int(possibleNumber)返回的可选 Int包含一个值,创建一个叫做 actualNumber的新常量并将可选包含的值赋给它。”
如果转换成功,actualNumber常量可以在if 语句的第一个分支中使用。它已经被可选类型 包含的 值初始化过,所以不需要再使用 ! 后缀来获取它的值。在这个例子中,actualNumber 只被用来输出转换结果。
你可以在可选绑定中使用常量和变量。如果你想在if语句的第一个分支中操作 actualNumber的值,你可以改成 if var actualNumber,这样可选类型包含的值就会被赋给一个变量而非常量。

9.隐式解析可选类型

可选类型暗示了常量或者变量可以“没有值”。可选可以通过 if语句来判断是否有值,如果有值的话可以通过可选绑定来解析值。
有时候在程序架构中,第一次被赋值之后,可以确定一个可选类型总会有值。在这种情况下,每次都要判断和解析可选值是非常低效的,因为可以确定它总会有值。
这种类型的可选状态被定义为隐式解析可选类型(implicitly unwrapped optionals)。把想要用作可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选类型

可选类型String 和隐式解析可选类型 String之间的区别:

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要惊叹号来获取值

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString  // 不需要感叹号

可以把隐式解析可选类型当做一个可以自动解析可选类型。你要做的只是声明的时候把感叹号放到类型的结尾,而不是每次取值的可选名字的结尾。

10.错误处理

func canThrowAnError() throws {
    // 这个函数有可能抛出错误
}

一个函数可以通过在声明中添加throws关键词来抛出错误消息。当你的函数能抛出错误消息时, 你应该在表达式中前置try关键词。

do {
    try canThrowAnError()
    // 没有错误消息抛出
} catch {
    // 有一个错误消息抛出
}

do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

11.断言

可选类型可以让你判断值是否存在,你可以在代码中优雅地处理值缺失的情况。然而,在某些情况下,如果值缺失或者值并不满足特定的条件,你的代码可能没办法继续执行。这时,你可以在你的代码中触发一个断言(assertion) 来结束代码运行并通过调试来找到值缺失的原因。

使用断言进行调试

断言会在运行时判断一个逻辑条件是否为 true。从字面意思来说,断言“断言”一个条件是否为真。你可以使用断言来保证在运行其他代码之前,某些重要的条件已经被满足。如果条件判断为 true,代码运行会继续进行;如果条件判断为 false,代码执行结束,你的应用被终止

你可以使用全局assert(_:_:file:line:)函数来写一个断言。向这个函数传入一个结果为 true 或者 false 的表达式以及一条信息,当表达式的结果为 false 的时候这条信息会被显示:

let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// 因为 age < 0,所以断言会触发

在这个例子中,只有 age >= 0true 的时候,即 age 的值非负的时候,代码才会继续执行。如果 age 的值是负数,就像代码中那样,age >= 0false,断言被触发,终止应用。

*注意:当代码使用优化编译的时候,断言将会被禁用,例如在 Xcode 中,使用默认的 target Release 配置选项来 build 时,断言会被禁用。

当条件可能为假时使用断言,但是最终一定要保证条件为真,这样你的代码才能继续运行。断言的适用情景:
整数类型的下标索引被传入一个自定义下标实现,但是下标索引值可能太小或者太大。
需要给函数传入一个值,但是非法的值可能导致函数不能正常执行。
一个可选值现在是 nil,但是后面的代码运行需要一个非 nil 值。

12.基本运算符

赋值运算符
与 C 语言和 Objective-C 不同,Swift 的赋值操作并不返回任何值。

if x = y {
    // 此句错误, 因为 x = y 并不返回任何值
}

加法运算符也可用于 String 的拼接:

"hello, " + "world"  // 等于 "hello, world"

空合运算符(Nil Coalescing Operator)

空合运算符(a ?? b)将对可选类型 a 进行空判断,如果 a 包含一个值就进行解封,否则就返回一个默认值 b。表达式 a 必须是 Optional 类型。默认值 b 的类型必须要和 a 存储值的类型保持一致。.

区间运算符(Range Operators)

闭区间运算符(a...b)定义一个包含从 ab(包括 a 和 b)的所有值的区间。
半开区间运算符:半开区间(a..<b)定义一个从ab 但不包括 b的区间。

13.字符串

初始化空字符串 (Initializing an Empty String)

var emptyString = ""               // 空字符串字面量
var anotherEmptyString = String()  // 初始化方法
// 两个字符串均为空并等价。

空字符串的判断: .isEmpty

if emptyString.isEmpty {
    print("Nothing to see here")
}
// 打印输出:"Nothing to see here"

字符串是值类型(Strings Are Value Types)

SwiftString类型是值类型。

如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。
任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作

Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且在底层都是以结构体的形式所实现。

Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着您将字符串作为值类型的同时可以获得极高的性能。

使用字符(Working with Characters)

通过标明一个Character类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量:

let exclamationMark: Character = "!"

字符数组:

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// 打印输出:"Cat!🐱"

连接字符串和字符

字符串可以通过加法运算符(+)相加在一起(或称“连接”)创建一个新的字符串:
您也可以通过加法赋值运算符 (+=) 将一个字符串添加到一个已经存在字符串变量上:
可以用append()方法将一个字符附加到一个字符串变量的尾部

字符串插值 (String Interpolation)

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"

Unicode

Unicode 是一个国际标准,用于文本的编码和表示。 它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。

SwiftStringCharacter类型是完全兼容 Unicode 标准的。

Unicode 标量(Unicode Scalars)

可扩展的字形群集(Extended Grapheme Clusters)

使用 characters 属性的 indices属性会创建一个包含全部索引的范围(Range),用来在一个字符串中访问单个字符。

插入和删除 (Inserting and Removing)

字符串/字符可以用等于操作符(==)和不等于操作符(!=)

前缀/后缀相等 (Prefix and Suffix Equality)

14.集合类型 (Collection Types)

SwiftArraysSetsDictionaries类型被实现为泛型集合

Swift 语言提供ArraysSetsDictionaries三种基本的集合类型用来存储集合数据。数组(Arrays)是有序数据的集。集合(Sets)是无序无重复数据的集。字典(Dictionaries)是无序的键值对的集。

在我们不需要改变集合的时候创建不可变集合是很好的实践。如此 Swift 编译器可以优化我们创建的集合。

1)数组:

创建一个空数组

var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")

可以使用append(_:)方法在数组后面添加新的数据项:
使用加法赋值运算符(+=)也可以直接在数组后面添加一个或多个拥有相同类型的数据项

shoppingList += ["Baking Powder"]
// shoppingList 现在有四项了
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList 现在有七项了

调用数组的insert(_:atIndex:)方法来在某个具体索引值之前添加数据项:

shoppingList.insert("Maple Syrup", atIndex: 0)
// shoppingList 现在有7项
// "Maple Syrup" 现在是这个列表中的第一项

类似的我们可以使用removeAtIndex(_:)方法来移除数组中的某一项。

for item in shoppingList {
    print(item)
}

for (index, value) in shoppingList.enumerate() {
    print("Item \(String(index + 1)): \(value)")
}

Swift的所有基本类型(比如String,Int,DoubleBool)默认都是可哈希化的,可以作为集合的值的类型或者字典的键的类型。没有关联值的枚举成员值(在枚举有讲述)默认也是可哈希化的。

2)集合

3)字典

字典是一种存储多个相同类型的值的容器。每个值(value)都关联唯一的键(key),键作为字典中的这个值数据的标识符。和数组中的数据项不同,字典中的数据项并没有具体顺序。我们在需要通过标识符(键)访问数据的时候使用字典,这种方法很大程度上和我们在现实世界中使用字典查字义的方法一样。

SwiftDictionary类型被桥接到FoundationNSDictionary类。
一个字典的Key类型必须遵循Hashable协议,就像Set的值类型。

var namesOfIntegers = [Int: String]()
// namesOfIntegers 是一个空的 [Int: String] 字典

namesOfIntegers[16] = "sixteen"
// namesOfIntegers 现在包含一个键值对

namesOfIntegers = [:]
// namesOfIntegers 又成为了一个 [Int: String] 类型的空字典

一个键值对是一个key和一个value的结合体

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

`airports`字典被声明为变量(用`var`关键字)而不是常量(`let`关键字)因为后来更多的机场信息会被添加到这个示例字典中。

作为另一种下标方法,字典的updateValue(_:forKey:)方法可以设置或者更新特定键对应的值。就像上面所示的下标示例,updateValue(_:forKey:)方法在这个键不存在对应值的时候会设置新值或者在存在时更新已存在的值。和上面的下标方法不同的,updateValue(_:forKey:)这个方法返回更新值之前的原值。这样使得我们可以检查更新是否成功。

可以使用下标语法来通过给某个键的对应值赋值为nil来从字典里移除一个键值对

 airports["APL"] = "Apple Internation"
// "Apple Internation" 不是真的 APL 机场, 删除它
airports["APL"] = nil
// APL 现在被移除了

removeValueForKey(_:)方法也可以用来在字典中移除键值对。这个方法在键值对存在的情况下会移除该键值对并且返回被移除的值或者在没有值的情况下返回nil

 if let removedValue = airports.removeValueForKey("DUB") {
    print("The removed airport's name is \(removedValue).")
} else {
    print("The airports dictionary does not contain a value for DUB.")
}
// prints "The removed airport's name is Dublin Airport."

我们可以使用for-in循环来遍历某个字典中的键值对。

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}
// YYZ: Toronto Pearson
// LHR: London Heathrow

通过访问keys或者values属性,我们也可以遍历字典的键或者值:
airports.keysairports.values
构造函数:

let airportCodes = [String](airports.keys)
// airportCodes 是 ["YYZ", "LHR"]

Swift 的字典类型是无序集合类型。为了以特定的顺序遍历字典的键或值,可以对字典的keysvalues属性使用sort()方法。

15.函数

函数 是一段完成特定任务的独立代码片段。你可以通过给函数命名来标识某个函数的功能,这个名字可以被用来在需要的时候"调用"这个函数来完成它的任务。

输入输出参数(In-Out Parameters)

函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误(compile-time error)。这意味着你不能错误地更改参数值。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数(In-Out Parameters)。

定义一个输入输出参数时,在参数定义前加 inout 关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。想获取更多的关于输入输出参数的细节和相关的编译器优化,请查看输入输出参数一节。

你只能传递变量给输入输出参数。你不能传入常量或者字面量(literal value),因为这些量是不能被修改的。当传入的参数作为输入输出参数时,需要在参数名前加 & 符,表示这个值可以被函数修改。

可变参数 (Variadic Parameters)

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容