https://www.bilibili.com/video/BV1rb411C7eN?p=5
1. mutating func
- struct结构里的方法func需要加上mutating修饰,代表它修改了struct中的属性,否则不能修改struct中的属性
- struct结构里的属性var不需要加mutating,var默认是可写的,所以是可改变的,用let修饰的为常量,是不可修改的
2. 为什么需要struct和class
- struct是值类型,它不存储在堆中,当struct被传递时,它会被复制而不是传递指针,但是复制struct是十分耗费时间和资源的,swift只有当struct改变时才会复制,这时所谓的 copy-on-write 语法。
- class只在堆中存储了一份,当被传递时,只是指针被复制,可以有很多个指针指向同一个class
3. swift中的构建数据结构的四个概念
- class , struct , enum , protocol
4. Protocol(协议)
- 简单来说,protocol是一个没有具体实现的方法和属性的列表(原文:a list of methods and vars with no implementation)
protocol
4.1 为什么要有protocol
- protocol的特点:调用者在调用protocol中的方法时可以使用任意内容(class,struct,enum),而protocol的接收方法可以接收到它想要的内容(Int,String,tuple ...)。
4.2 使用protocol的好处
- 非常适合无目的而结构化的通信(原文:blind structured communication),在view和view controller的通信之中,view是非常宽泛的,而view controller是非常具体的
4.3 protocol的三个组成要素
- 协议声明 (属性和方法),协议并不储存这些vars
- 一个class,struct,enum声明遵守一个协议protocol
- 这个class,struct,enum完成这个协议声明的方法,协议中的vars由这些class,struct,enum存储
- 注意:swift协议中的所有方法都必须被实现,而objective-c中允许协议中的方法允许可选
-
如果一个类遵守某协议,而且该协议中有init(),在该class中必须用required修饰init()
image.png
4.4 protocol是一种type,它可以跟在变量后面(let BMW:Movable = Car())
image.png
image.png
4.5 delegate
协议和代理使用的六个步骤
- 一个view声明一个代理协议
- 这个view生命一个weak delegate的属性
- view用这个delegate去做(获得)一些自己无法拥有或者控制的事情
- 某个Controller声明它实现这个协议
- Controller将自己设为这个weak delegate属性,这样原来的view就可以控制这个Controller
- Controller实现协议里的方法(可以有不必要实现的)
5 String
image.png
- String.startIndex //第一个字符索引
- String.index( _ : index ,offsetBy : Int) //按照字符的偏移量获得索引,因为字符串的索引不是整数,所以需要用偏移量来确定
- index( of : ) //可能返回nil,寻找某个字符的索引
- [String,index1 ..< String.index2] 这是一个可数区间,
- String.component(separatedBy: " ") // 返回一个数据Array<String>
- 用let arr = Array<String>来初始化一个character数据,这样就能用int来当索引
- ..< 如果左边没有内容,默认从头开始,右边没内容则默认一直到末尾
6 NSAttributedString
NSAttributedString.png
- 可以在outlet后面的可以添加{ didset{} }来设置NSAttributedString
7 Function Type
image.png
- 函数可以当作成方法中的参数
8 闭包
闭包
//函数写法
func changeSign(x:Double) -> Double { return -x}
//闭包写法:将大括号移到最顶端,并在原来的地方用in替代
let changeSign = {(x:Double) -> Double in return -x}
//由于swift能自动推断类型,所以闭包可以简写成下面这样
let changeSign = {(x) in return -x}
//甚至可以省去return
let changeSign = {(x) in -x}
//可以用$1,$2,$3来替代第一个第二个第三个参数,所以还能化简成下面这样
let changeSign = {-$1}
//func changeSign(x:Double) -> Double { return -x} 和 {-$1} 实现了完全一样的功能,这就是闭包的魅力!
8.1 如何在方法的参数中使用闭包
-
Array中有一个方法.map,它接收一个函数作业参数,可以将Array中的每个元素进行操作后返回一个新的Array
尾随闭包
-
在闭包后加小括号()可以立即执行闭包,对于lazy修饰的属性,十分有用
利用闭包初始化属性
- 闭包可以自动捕获上下文的变量,闭包是引用类型!Swift中只有两种引用类型,class和闭包!
-
假如将闭包加入数组,这个数组就有一个指针指向闭包,来保证闭包中的变量存活,闭包中的变量在闭包消失后才会被释放
闭包自动捕获
- 如果闭包中捕获了一个类的变量,这个闭包就会在堆中指向这个类,如果这个类的变量中又包含这个闭包,那么这个类又会在堆中指向这个闭包,它们在内存中互相指向,形成了一个死循环,导致内存泄漏。
let arr = [1,-3,100,0,-1, 8]
let arrBiggerThanZero = arr.filter( { $0 > 0 } ) // arrBiggerThanZero = [1,100,0,8]
// let xxx = Array.filter { $0 > 0 } 尾随闭包写法
- filter函数会接收一个函数作为参数,对每一个Array中的元素进行判断,对于返回所有true的元素重组一个新Array返回。比如Array.filter( { $0 > 0 } ) 会对每一个元素进行是否大于0的判断,对于所有大于0 的元素组合成一个新的数据返回
//神扩展
extension Collection {
var oneAndOnly: Element? {
return count == 1 ? first : nil //count是该集合的数量,first是该集合的第一个元素
}
}
//应用
let ch = "Hello".oneAndOnly // ch == nil
let ch = "H".oneAndOnly // ch == H











网友评论