本章内容概览:Swift中的类与结构体、常用操作数组函数式方法
上一节:【iOS】01_Swift基础语法(简介、语法基础、基础类型介绍)
下一节:【iOS】03_Swift基础语法(控制流、集合)
同系列文章请查看:快乐码元 - iOS篇
Ⅰ.类和结构体
1.类
类可以定义属性、方法、构造器、下标操作。类使用扩展来扩展功能,遵循协议。类还可以继承,运行时检查实例类型。
与其他编程语言所不同的是,Swift 并不要求你为自定义类去创建独立的接口和实现文件。你所要做的是在一个单一文件中定义一个类,系统会自动生成面向其它代码的外部接口。
1.1 类和结构体对比
Swift 中类和结构体 有很多共同点。共同处在于:
定义属性用于存储值
定义方法用于提供功能
定义附属脚本用于访问值
定义构造器用于生成初始化值
通过扩展以增加默认实现的功能
符合协议以对某类提供标准功能
与结构体相比,类还有如下的附加功能:
继承允许一个类继承另一个类的特征
类型转换允许在运行时检查和解释一个类实例的类型
解构器允许一个类实例释放任何其所被分配的资源
引用计数允许对一个类的多次引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class C { var p: String init (_ p : String ) { self .p = p } subscript (s : String ) -> String { get { return p + s } set { p = s + newValue } } } let c = C ("hi" )print (c.p)print (c[" ming" ])c["k" ] = "v" print (c.p)
1.2 恒等运算符
因为类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。
为了能够判定两个常量或者变量是否引用同一个类实例,Swift 内建了两个恒等运算符:
恒等运算符
不恒等运算符
运算符为:===
运算符为:!==
如果两个常量或者变量引用同一个类实例则返回 true
如果两个常量或者变量引用不同一个类实例则返回 true
1.3 结构体
我们可以为结构体定义属性(常量、变量)和添加方法,从而扩展结构体的功能。
与 C 和 Objective C 不同的是:
结构体不需要包含实现文件和接口。
结构体允许我们创建一个单一文件,且系统会自动生成面向其它代码的外部接口。
结构体总是通过被复制的方式在代码中传递,因此它的值是不可修改的。
1 2 3 4 5 6 struct nameStruct { Definition 1 Definition 2 …… Definition N }
1 2 3 4 5 6 7 8 9 10 11 12 struct MarksStruct { var mark: Int init (mark : Int ) { self .mark = mark } } var aStruct = MarksStruct (mark: 98 )var bStruct = aStruct bStruct.mark = 97 print (aStruct.mark) print (bStruct.mark)
结构体是值类型,可以定义属性、方法、构造器、下标操作。结构体使用扩展来扩展功能,遵循协议。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 struct S { var p1: String = "" var p2: Int } extension S { func f () -> String { return p1 + String (p2) } } var s = S (p2: 1 )s.p1 = "1" print (s.f())
1.4 属性
类、结构体或枚举里的变量常量就是他们的属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 struct S { static let sp = "类型属性" var p1: String = "" var p2: Int = 1 var cp: Int { get { return p2 * 2 } set { p2 = newValue + 2 } } var rcp: Int { p2 * 4 } } print (S .sp)print (S ().cp) var s = S ()s.cp = 3 print (s.p2) print (S ().rcp)
willSet 和 didSet 是属性观察器,可以在属性值设置前后插入自己的逻辑处理。
键路径表达式作为函数:
1 2 3 4 5 6 7 8 9 10 struct S2 { let p1: String let p2: Int } let s2 = S2 (p1: "one" , p2: 1 )let s3 = S2 (p1: "two" , p2: 2 )let a1 = [s2, s3]let a2 = a1.map(\.p1)print (a2)
1.5 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 enum E : String { case one, two, three func showRawValue () { print (rawValue) } } let e = E .threee.showRawValue() struct S { var p: String mutating func addFullStopForP () { p += "." } } var s = S (p: "hi" )s.addFullStopForP() print (s.p)class C { class func cf () { print ("类方法" ) } }
static和class关键字修饰的方法类似 OC 的类方法。static 可以修饰存储属性,而 class 不能;class 修饰的方法可以继承,而 static 不能。在协议中需用 static 来修饰。
静态下标方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 struct S2 { static var sp = [String : Int ]() static subscript (_ s : String , d : Int = 10 ) -> Int { get { return sp[s] ?? d } set { sp[s] = newValue } } } S2 ["key1" ] = 1 S2 ["key2" ] = 2 print (S2 ["key2" ]) print (S2 ["key3" ])
自定义类型中实现了 callAsFunction() 的话,该类型的值就可以直接调用。
1 2 3 4 5 6 7 8 9 10 struct S3 { var p1: String func callAsFunction () -> String { return "show \(p1) " } } let s2 = S3 (p1: "hi" )print (s2())
1.6 继承
类能继承另一个类,继承它的方法、属性等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class C1 { var p1: String var cp1: String { get { return p1 + " like ATM" } set { p1 = p1 + newValue } } init (p1 : String ) { self .p1 = p1 } func sayHi () { print ("Hi! \(p1) " ) } } class C2 : C1 { var p2: String init (p2 : String ) { self .p2 = p2 super .init (p1: p2 + "'s father" ) } } C2 (p2: "Lemon" ).sayHi() class C3 : C2 { override func sayHi () { print ("Hi! \(p2) " ) } } C3 (p2: "Lemon" ).sayHi() class C4 : C1 { override var cp1: String { get { return p1 + " like Out of the blade" } set { p1 = p1 + newValue } } } print (C1 (p1: "Lemon" ).cp1) print (C4 (p1: "Lemon" ).cp1)
通过 final 关键字可以防止类被继承,final 还可以用于属性和方法。使用 super 关键字指代父类。
2.函数式
js:这个我熟
2.1 map
map 可以依次处理数组中元素,并返回一个处理后的新数组 。
1 2 3 4 5 let a1 = ["a" , "b" , "c" ]let a2 = a1.map { "\($0 ) 2" } print (a2)
使用 compactMap 可以过滤 nil 的元素。flatMap 会将多个数组合成一个数组返回。
2.2 filter
根据指定条件返回
1 2 3 4 5 let a1 = ["a" , "b" , "c" , "call my name" ]let a2 = a1.filter { $0 .prefix(1 ) == "c" } print (a2)
2.3 reduce
reduce 可以将迭代中返回的结果用于下个迭代中,还能让你设个初始值。
1 2 3 4 5 6 7 let a1 = ["a" , "b" , "c" , "call my name." , "get it?" ]let a2 = a1.reduce("Hey u," , { partialResult, s in partialResult + " \(s) " }) print (a2)
2.4 sorted
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 let a1 = ["a" , "b" , "c" , "call my name." , "get it?" ]let a2 = a1.sorted()let a3 = a1.sorted(by: > )let a4 = a1.sorted(by: < )print (a2) print (a3) print (a4) struct S { var s: String var i: Int } let a5 = [S (s: "a" , i: 0 ), S (s: "b" , i: 1 ), S (s: "c" , i: 2 )]let a6 = a5 .sorted { l, r in l.i > r.i } .map { $0 .i } print (a6)
参考资料:
Tips:
Please indicate the source and original author when reprinting or quoting this article.