Swift语法学习笔记1:变量与数据类型

我把自己学习Swift语法的笔记通过4篇左右的文章分享给大家。由于是个人笔记,代码较多,配的文字很少,对于Swift初学者的理解可能会造成一些困难。

我会在《Swift语法学习笔记》系列中覆盖以下内容:

  • Swift常量与变量
  • Swift常用数据类型
    • 基本数据类型
    • 集合类型
    • 可选类型
  • 流程控制
    • if语句
    • for循环
    • while语句
    • repeat语句
    • Switch语句
  • 函数和闭包
    • 函数
    • 闭包
  • 结构体
    • 定义与使用结构体
    • 结构体的初始化方法
    • 继承

本篇是《Swift语法学习笔记》系列的第一篇文章,将涵盖以下内容:

  • Swift常量与变量
  • Swift常用数据类型
    • 基本数据类型
      • 整型
      • 字符串类型
      • 布尔类型
      • 枚举类型
    • 集合类型
      • 数组
      • 字典
      • Sets
      • NSArray、NSDictionary、NSSet
    • 可选类型
      • Swift郑家可选类型的原因
      • 获取可选类型的真实值
      • 获取字典中不存在的默认值
      • 枚举类型中的可选类型
      • as与as!的区别
      • as?

1 常量与变量

1.1 常量

Swift使用let声明常量,必须在声明的同时进行初始化赋值,且其值不可更改。

1.2 变量

Swift使用var声明变量:

var str = "Hello World!"    //Swift会自动推定str的类型为String,编译器一旦完成类型推定,此后的代码均不可以修改变量的类型

或者

var str : String
str = "Hello World"

2 数据类型

2.1 基本数据类型

2.1.1 Int整型

获取Int数据类型的最小值与最大值:

Int8.min
Int8.max
UInt32.min
UInt32.max

各种进制的表示方法:

let decimal = 123        // Value is 123
let octal = 0o77         // Octal 77 = decimal 63
let hex = 0x1234         // Hex 1234 = decimal 4660
let binary = 0b1010      // Binary 1010 = decimal 10

为了更好的可读性,在赋值时可以使用“_”分隔数字:

let v = -1_234     // Same as -1234
let w = 12_34_56   // Same as 123456

声明常量的同时指定数据类型:

let a = 1.23         // This is inferred to be a Double
let b: Float = 1.23  // Forced to be Float

Swift不可以做如下形式的类型推定:

let a = 123
let b = 0.456
let c = a + b  //由于a为Int类型,b为Double类型,所以编译器不能决定c到底是什么类型

若要成功编译,需要将a转换为Double类型

let a = 123
let b = 0.456
let c = Double(a) + b

2.1.2 String类型

使用转译符“\”在字符串中插入双引号:

let quoted = "Contains \"quotes\"" // Contains "quotes"

插入反斜杠:

let backslash = "\\" // Result is \

插入换行符与缩进符:

let specialChars = "Line1\nLine2\tTabbed"

插入数值:

print("The value of pi is \(M_PI)") // Prints "The value of pi is 3.14159265358979\n"

插入表达式:

// This code prints: "Area of a circle of radius 3.0 is 28.2743338823081\n"
let r = 3.0
print("Area of a circle of radius \(r) is \(M_PI * r * r)")

字符串相加:

let s = "That's one small step for man, " + "one giant leap for mankind"
print(s)         // "That's one small step for man, one giant leap for mankind\n"

比较字符串:

let s1 = "String one"
let s2 = "String two"
let s3 = "String " + "one"
s1 == s2         // false: strings are not the same
s1 != s2         // true: strings are different
s1 == s3         // true: strings contain the same characters.

获取字符串的长度:

s3.characters.count  // 10
s3.utf16.count       // 10

字符类型只能包含一个字符,且必须用双引号包围。

let c: Character = "s"

不能使用“+”运算符将字符串与字符相加,需要使用字符串的append方法:

let c: Character = "s"
var s = "Book"   // "var" because we want to modify it
s += c           // Error – illegal
s.append(c)      // "Books"

Swift中的字符串等简单数据类型都是“拷贝类型”(只有类除外,类是“引用类型”):

var s1 = "Book"
var s2 = s1     // s2 is now a copy of s1
s2 += "s"       // Appends to s2; s1 is unchanged
s1     // "Book"
s2     // "Books"

2.1.3 Bool类型

var b = true // Inferred type is Bool
var b1: Bool
b1 = false

2.1.4 enum枚举类型

定义枚举类型:

enum DaysOfWeek {
    case Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}

或者

enum DaysOfWeek {
    case Sunday
    case Monday
    case Tuesday
    case Wednesday
    case Thursday
    case Friday
    case Saturday
}
var day = DaysOfWeek.Sunday       // "day" is inferred to be of type "DaysOfWeek"
day = .Friday                     // Note that the "." Is required

包含其他数据类型的枚举:

enum Status {
    case OK
    case ERROR(String)
}
let status = Status.OK
let failed = Status.ERROR("That does not compute")    //这里的failed被推定为什么类型?

含有原始值的枚举:

enum DaysOfWeek : Int {
    case Sunday = 0 // 0
    case Monday     // 1
    case Tuesday    // 2
    case Wednesday  // 3
    case Thursday   // 4
    case Friday     // 5
    case Saturday   // 6
}

或者

enum DaysOfWeek : Int {
    case Sunday = 0
    case Monday         // 1
    case Tuesday        // 2
    case Wednesday      // 3
    case Thursday       // 4
    case Friday = 20    // 20
    case Saturday       // 21
}
var day = DaysOfWeek.Saturday
let rawValue = day.rawValue         // 21 rawValue位Int类型

原始值为字符串的枚举:

enum ResultType : String {
    case SUCCESS = "Success"
    case WARNING = "Warning"
    case ERROR = "Error"
}
let s = ResultType.WARNING.rawValue     // s = "Warning"为String类型

通过指定枚举类型的原始值可以获取对应的“枚举值”:

let result = ResultType(rawValue: "Error")      // 返回ERROR,result的类型为ResultType?可选类型,具体可以参照“3 可选类型”

2.2 集合类型

2.2.1 数组

声明数组:

var integers = [1, 2, 3]
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

或者

var integers: [Int] // [Int] means "array of Ints"
integers = [1, 2, 3]

空数组

var empty: [String] = []

数组的索引范围:

var integers = [1, 2, 3]
integers[1..<3]               // Get elements 1 and 2 as an array. Result is [2, 3]
integers[1..<3] = [4]         // Replace elements 1 and 2 with [4]. Result is [1, 4]
integers = [1, 2, 3]
integers[0...1] = [5, 4]      // Replace elements 0 and 1 with [5, 4]. Result is [5, 4, 3]

增加新元素:

var integers = [1, 2, 3]
integers.append(4)             // Result is [1, 2, 3, 4]

或者

integers.insert(-1, atIndex: 0)     // Result is [-1, 1, 2, 3, 4]

或者

var integers = [1, 2, 3]
let a = integers + [4, 5]      // a = [1, 2, 3, 4, 5]; integers array unchanged
integers += [4, 5]             // Now integers = [1, 2, 3, 4, 5]

删除元素:

var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
days.removeAtIndex(3)               // Removes "Wednesday" and returns it to the caller
days.removeRange(0..<4)             // Leaves ["Friday", "Saturday"]
days.removeAll(keepCapacity: false) // Leaves an empty array

常量数组一旦初始化,不可更改其值:

let integers = [1, 2, 3]       // Constant array
integers = [4, 5, 6]           // Error: cannot replace the array
integers[0] = 2                // Error: cannot reassign elements
integers.removeAll(keepCapacity: false)     // Error: cannot modify content

验证复制特性:

var integers = [1, 2, 3]
var integersCopy = integers    // Creates a copy of "integers"
integersCopy[0] = 4            // Does not change "integers"
integers          // [1, 2, 3]
integersCopy      // [4, 2, 3]

检查数组中是否存在某个值:

let integers = [1, 2, 3]
integers.contains(2) // true
integers.contains(4) // false

获取数组中某个值的索引值:

let integers = [1, 2, 3]
let index = indexOf(3)!.value // Result is 2

2.2.2 字典

声明一个类型为[String, Int](<String, Int>)的字典:

var dict = ["Red": 0,
            "Green": 1,
            "Blue": 2]

或者

var dict: [String: Int]
dict = ["Red": 0, "Green": 1, "Blue": 2]

获取字典值:

let value = dict["Red"]         // Result is 0, the value mapped to the key "Red"

获取字典的键值对总数:

var dict = ["Red": 0, "Green": 1, "Blue": 2]
dict.count     // 3

修改字典值:

dict["Yellow"] = 3     // Adds a new value with key Yellow
dict["Red"] = 4        // Updates the value with key Red

删除字典值:

var dict = ["Red": 0, "Green": 1, "Blue": 2]
dict.removeValueForKey("Red")     // Removes value with key "Red"
dict.removeAll()                  // Empties the dictionary

常量字典不能修改:

let fixedDict = ["Red": 0, "Green": 1, "Blue": 2]
fixedDict["Yellow"] = 3             // Illegal
fixedDict["Red"] = 4                // Illegal
fixedDict = ["Blue", 7]             // Illegal
fixedDict.removeValueForKey["Red"]  // Illegal

2.2.3 集合Sets(无序数组)

声明Set:

let s1 = Set([1, 2, 3])

或者

let s2: Set<Int> = [1, 2, 3]

是否含有某元素:

s1.contains(1)  // true
s2.contains(4)  // false
s1.count        // 3

增加元素:

var s1 = Set([1, 2, 3])  // [2, 3, 1] (note that order does not matter in a set)
s1.insert(4)             // [2, 3, 1, 4]

删除元素:

s1.remove(1)           // [2, 3, 4]
s1.removeAll()         // [] (empty set)

2.2.4 NSArray, NSDictionary and NSSet

声明一个NSString:

let s: NSString = "Red,Green,Blue"

使用NSString:

let s: NSString = "Red,Green,Blue"
let components = s.componentsSeparatedByString(",") // Calls the NSString method
components     //[String]类型的["Red", "Green", "Blue"]

使用NSDictionary:

let d = NSDictionary()

强制转换

let e = d as Dictionary

或者

let d = NSDictionary()
let e = d as! [String: String]

2.3 可选类型

2.3.1 Swift增加可选类型的原因

var dict: [String: Int];
dict = ["Red": 0, "Green": 1, "Blue": 2]
let value = dict["Red"]         //the inferred type for value is not Int, but Int?—an optional integer

Swift中为什么会增加可选类型呢?考虑这种情况:

let yellowValue = dict["Yellow"]

What value should be assigned to yellowValue? Most languages address this by having a distinguished value that means, by convention, “no value.” In Objective-C, this value is referred to as nil (which is really just a redefinition of 0); in C and C++ it’s NULL (again, a redefinition of 0); and in Java it’s null.
The problem with this is that it can be dangerous to use a nil (or equivalent) value. In Java, for example, using a null reference causes an exception; in C and C++, the application is likely to crash.What's worse, there's no way to know from its declaration whether a variable might contain a null (or nil or NULL) value.
Swift solves this problem in a neat way: it has a nil value, but a variable (or constant) can only be set to nil if it's declared as an optional, or its type is inferred to be optional. As a result, you can tell immediately whether a variable or constant could be nil by examining its type: if it's not optional, it can't be nil. Further to that, Swift requires you to take that into account explicitly whenever you use the value.

不能赋值nil给非可选类型赋值nil:

var color = "Red"
color = nil     // Illegal: color is not an optional type.

不能赋值可选类型给非可选类型:

let dict = [0: "Red", 1: "Green", 2: "Blue"]
color = dict[0]     // Illegal: value of dict[0] is optional string, color is not optional.

可以将可选类型赋值给可选类型(或者未初始化的常量与变量):

let dict = [0: "Red", 1: "Green", 2: "Blue"]
var color: String?     // "String?" means optional String,color的值为nil
color = dict[0]        // Legal
print(color)           // printed is not“Red” but Optional("Red"),这其实是一个装箱(wrapped)后的值

2.3.2 获取可选类型的值

为了得到可选类型的实际值,需要对可选类型进行Unwrap(拆箱)操作:

let actualColor = color!         // "color!" means unwrap the optional, actualColor是String类型

上面的操作其实可以理解为强制拆箱操作,不论其值是否真的存在,这么做其实是很危险的。试看以下操作:

let dict = [0: "Red", 1: "Green", 2: "Blue"]
let color = dict[4]          //color是String?类型,其值为nil
let actualColor = color!     //对值nil的可选类型进行拆箱,会造成程序崩溃

为了避免发程序崩溃,需要对可选类型进行安全检查:

if color != nil {
    let actualColor = color!
}

或者

if let actualColor = color {
    // Executed only if color was not nil
    print(actualColor)
}

或者

if var actualColor = color {
    // Executed only if color was not nil. actualColor can be modified
    print(actualColor)
}

或者

if var color = color {
    // Executed only if the value of the original color variable was not nil
    print(color) // Refers to the new variable, holding the unwrapped value
}

或者

let dict = [0: "Red", 1: "Green", 2: "Blue"]
let color = dict[0]
if var color = color {
    // Executed only if color was not nil
    print(color)         // "Red"
    color = "Green"       // Reassigns the local variable
}         // New color variable is now out of scope
color     // Refers to the original value: "Red"

2.3.3 获取字典中不存在的默认值

let dict = [0: "Red", 1: "Green", 2: "Blue"]
let color = dict[4]
let actualColor = color ?? "Blue"

或者

let dict = [0: "Red", 1: "Green", 2: "Blue"]
let actualColor = dict[4] ?? "Blue"

2.3.4 枚举类型中的可选类型

enum ResultType : String {
    case SUCCESS = "Success"
    case WARNING = "Warning"
    case ERROR = "Error"
}
let result = ResultType(rawValue: "Invalid")     //result为ResultType?类型,其值为nil

!可选类型的作用:

let dict = [0: "Red", 1: "Green", 2: "Blue"]
var color: String!         // Notice the !,这个操作告诉编译器color永远不可能为    nil值
color = dict[0]            // Assigns Optional("Red")
print(color)               // Automatically unwraps the optional

2.3.5 as与as!的区别

Roughly speaking, you use as when the cast is guaranteed to work and as! when it’s not—the ! expresses the fact that you are forcing the compiler to accept code that it would otherwise report an error for, such as when downcasting.

as可以用于子类向父类的转换:

let s = "Fred"
let n = s as NSString

或者

let label = UILabel()
let view = label as UIView

as!用于父类向子类的强制转换,或未知类向任意类的转换:

let view: UIView = UILabel()
let label = view as! UILabel     // Downcast requires !

或者

let d = NSDictionary(objects: ["Red", "Green", "Blue"], forKeys: [0, 1, 2])
let color = d[1] as! String

2.3.6 as?

let d = NSDictionary(objects: ["Red", "Green", "Blue"], forKeys: [0, 1, 2])

获取值:

let color = d[1]     // Gets an optional-AnyObject?, wrapping "Green"

或者

let color = d[1] as! String

注意以下的错误代码:

let d = NSDictionary(objects: [ 0, 1, 2], forKeys: [0, 1, 2])
let value = d[1] as! String     //crash happened

为了防止这种情况发生,需要使用as?:

The as? operator returns an optional: if its first operand is not of the type given by its second operand, it returns nil instead of crashing

let d = NSDictionary(objects: [ 0, 1, 2], forKeys: [0, 1, 2])
if let value = d[1] as? String {     // as? returns nil if d is not of type String?
    print("OK")     // As expected – use value as normal
} else {
    print("Incorrect types")     // Executed if d is not of type [Int: String]
}

或者

You can use the is keyword to check whether the dictionary is of the expected type before using it:

if d is [Int: String] { // Evaluate to true if d maps Ints to Strings
    print("Is [Int: String]")
} else {
    print("Incorrect types")
}

参考文献

《Beginning iPhone Development with Swift 2 - Exploring the iOS SDK 》From page 777 to page 838.

联系作者

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

推荐阅读更多精彩内容

  • Swift 介绍 简介 Swift 语言由苹果公司在 2014 年推出,用来撰写 OS X 和 iOS 应用程序 ...
    大L君阅读 3,230评论 3 25
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,817评论 1 10
  • 基础部分(The Basics) 当推断浮点数的类型时,Swift 总是会选择Double而不是Float。 结合...
    gamper阅读 1,298评论 0 7
  • 一直没有时间好好看一下swift,最近复习了一遍语法,这里记录swift学习过程中遇到的一些问题和要点,和Obje...
    bomo阅读 2,360评论 0 25
  • 上图是我最佳拍档、今天与他分享了中国式众筹:杨众筹首倡的中国式众筹是在众创实践中产生的重大理论创新,是经系列案例验...
    南辉阅读 155评论 0 0