swift 官方教程 学习笔记

1、范型
范型所解决的问题

函数、方法、类型:类,结构体,枚举,元组类型,协议
参数,返回值,成员函数参数,成员属性
类型不确定, 就用一个范型, 可以根据实參指定的类型,动态改变类型

在 函数的名字后面 用尖括号表示
在 类型的定义 类型名字后面, 用尖括号表示

范型函数
返回类型是范型
传入参数是范型

类型参数

占位类型

命名类型参数
类型参数 是有一个描述性名字的

Dictionary<Key,Value>

范型类型

类型: 枚举,类, 结构体,元组
类型 定义的时候,使用范型, 表示,它的属性成员,函数成员, 中定义的类型, 不是特定的,而是可以通过实參来指定

扩展范型类型

扩展一个范型类型时, 原始类型中声明的范型类型占位符,在扩展中可以使用这些类型占位符。不需要重新定义

类型约束

正是由于,类型不是固定的,可以随便指定的。 实际中, 我们并不要求是任意的所有类型,
而是要求类型,有一定的限制。
什么限制? 要求类型符合: 某协议,某协议组合, 继承自某父类
这是类型限制,
还有 : 取值的大小有一定的范围
怎么表示约束呢?
范型函数 约束 表示方法:
用分号:

范型类型 约束表示方法:
用分号:

关联类型

协议中的属性、方法, 可以使用范型类型,
不需要协议名后面加尖括号范型, 而是在协议的定义中
用关键字:associatedtype 范型类型占位符 的一条语句来实现。
如果某个, 结构体,类,枚举, 定义为需要实现该协议。
可以在类型的定义中,typealias指定 协议中的associatedtype关联类型指定实际的类型的名称

扩展:让一个 已经存在的类型 符合某个协议
extentesion Array: MyCoustomSomeeeeProtocol {}
protocol MyCoustomSomeeeeProtocol {
func printHllo()
}

where子句

func afaf<T:sommetype, Q:asdfasType
where T.asdf == Q.asdf,
T.asdfasdf:HelloClass

(aaa:T, bbb:Q) -> (T, Q) {

}

函数

闭包
闭包:传入一个闭包。
闭包实现体中,闭包接受者、传递闭包者

1, 读取这个参数。 闭包接受者,把创建好的参数传入闭包,给闭包读去使用
使用场景是: alamofire 的闭包, uploadTaskWithRequest的闭包
通常这个参数是struct类型

2, 修改这个参数。 传递闭包者, 把从接受者那里拿到的参数, 通过一定的滤斗行为, 修改这个值。 接受者,后面会从新拿回被传递者处理过的参数。
使用场景是:snapkit、sqlite.swift
通常这个参数是class类型

闭包表达式

尾随闭包
值捕获
闭包是引用类型
非逃逸闭包
自动闭包

//do-catch
//try?
//try!
//do-catch 模式
do {
let a = try tryGetString(false)
print(a)
} catch let a {
let a = a as! MyError
switch a {
case .ErrorGet(let block):
block("Hello")
default:
logFlag()
}
}
do {
let a = try tryGetString(true)
print(a)
} catch {
let error = error as! MyError
switch error {
case .ErrorNetWork(let code, let reson):
print(code, reson)
default:
print("asd")
}
}
if let b = try? tryGetString(true) {
print(b)
}
logFlag()
//let _ = try! tryGetString(true)

logFlag()
func tryGetString(let test:Bool) throws -> String {
//写在可能抛出异常的语句前面,defer才可能被执行。
defer {
logFlag()
}
if test {
throw MyError.ErrorNetWork(code: "404", reson: "asdf")
} else {
throw MyError.ErrorGet(block: { (a:String) in
print(a)
})
}
defer {
logFlag()
}
defer {
logFlag()
}
defer {
logFlag()
}

return "s"

}
func tryGetStringGo() throws {
try tryGetString(true)

}
let seprator:String = "================="
func logFlag(let file:String = #file , let line: Int = #line, let funcname:String = #function) {

print(file, line, funcname, separator: seprator, terminator: "************")

}

try

错误处理

表示、 抛出错误
表示错误:ErrorType

throw 跟 return一样 不涉及解除调用栈
func getSmting()throw{
if a {
return “ok”
} else {
//throw 立即退出方法
throw a:ErrorType
}
}

处理错误

try?
try!
try : 必须处理这个错误
1,传递给调用这个try的函数:继续传递

func getAd()throws{
if let a = try getSmting() {
}
}

2,用do,catch
do {
try let a = getAd()
if a ! = nil {
}
} catch {
error
}

do {
try 表达式
语句

} catch{
error常量
}

do{
try 表达式
//如果没有抛出错误,下面的语句执行,否则转移到catch子句
语句
} catch 模式 {

} catch 模式2 where 条件 {

} catch {

3,将错误做为可选类型处理
let a:String?
a = getSmting()
if a {}

try?

4,断言此错误不会发生

有时候你知道throwing函数是不会抛出错误的
这种情况下,可以在表达式前面 写try!来禁用错误传递
这会把调用包装在一个有错误抛出的运行时断言中。
如果真的抛出错误,你会得到一个运行时错误
禁用错误传递
try!

指定清理操作
使用defer语句,在即将离开当前代码块执行的语句
该语句可以执行清理工作
不论是因为return离开、break离开、throw离开,
都可以执行defer中的语句
延迟到当前的作用域退出之前,这个语句的要求是
不能包含任何控制转移语句。比如break、return、throw

扩展语法
类,结构体,枚举,协议
如果写了扩展,则改类型 所有实例都可以用, 不管扩展的代码 写在 类型声明前面还是后面

属性, 类型属性: 只能是计算型的
不可以添加存储型。 不可以为已有属性添加观察器

类型属性、 类型方法 都不能被重写。 所以只能用static, 不管是struct,还是class,enum的类型属性、类型方法
struct aa {
class func aa(){}//errr:只能用static
}
struct aa{
class
}
类类型 的 存储属性不能 用class关键字, 因为class 关键字表示属性可以被重写, 然而类类型的存储属性 无论如何不能被重写, 所以要用static
类类型 可以用 static存储型属性 , 可以用计算型属性。
但是存储属性 不能被子类重写。所以存储属性要用static

实例方法、类型方法: static: 添加新的功能,不能重写已有的功能
可变实例方法:
mutating
extension Int{
mutating func square(){
self=self*self
}
}

定义下标:

定义和使用新的嵌套类型:

使用一个已有类型 符合 某个协议:

构造器

提供新的构造器:
为类添加 便利构造器
不能添加 新的指定构造器, 指定构造器和析gou qi

逐一成员构造器、指定构造器、默认构造器、便利构造器
构造器规则- 让所有成员完全初始化

方法

下标

嵌套类型

协议
类、结构体、枚举 符合 协议

协议语法
类、结构体、枚举 定义非常相似
父类放在前面, 协议放在后面

属性要求
声明属性 可读写

类型属性、类型方法, 用 static关键字

计算型、 存储型、 观察器、 下标,
常量计算型(没有常量计算型,因为计算型的值都是不确定,要加var, 计算型变量都是var的)、
变量计算型(只要是计算型, 都加var)、
只读计算型(get)
常量存储型
变量存储型
只读存储型(就是常量存储型)

结论: 协议总是用var来声明 属性。 类型后面加上{get set}可读可写,{get}可读

没有计算型常量:计算型变量只实现get方法
存储型变量、存储型常量、计算型变量
存储型常量=》计算型变量,实现get方法的计算型变量代替

属性要求,存储型,计算型。 无法获知。采纳协议时,可以定义为存储型变量 或者 计算型变量

协议 类型属性
协议中定义类型属性, 总是 使用 static关键字做为前缀,
类类型采纳协议时,可以使用class关键字来声明类型属性。
方法要求
协议中定义类方法, 总是 使用static关键字做为前缀,类类型采纳协议时,可以使用class关键字来做为前缀

类:
类型属性:
static , class
存储变量,存储型常量, 计算型变量
类型方法:
static, class
存储变量,存储型常量, 计算型变量
实例属性:
存储变量,存储型常量, 计算型变量
实例方法:

mutating方法要求 变异方法
在实例方法中修改值, 在结构体,枚举中,将mutating关键字做为方法的前缀, 写在func关键字前,表示该方法 可以修改 任意属性的值

构造器要求
init

协议做为类型
做为函数、方法、构造器中的参数类型 或 返回值类型
做为常量、变量、属性的类型
做为数组、字典、其他容器中的元素类型
协议也是一种类型。 协议类型的名称 应与 其他类型 的写法相同, 使用驼峰式写法

委托模式

通过 扩展 添加协议一致性
这里说的不是 扩展协议。
扩展协议,可以提供默认的实现:必须提供
也可以不提供默认的实现? 不可以

某个类,本来没有声明为符合某个协议,
然而,这个类,把它进行扩展, 在扩展中,声明为符合某个协议,
与这个类,直接声明为符合某个协议
作用是相同的。

扩展协议:扩展 方法、下标、属性、构造器
原来的协议

通过 扩展 采纳协议

protocol TextRepresentable {
var texualDescription:String
}
struct Hamster {
var name:String
//实现了协议要求的方法,却没有声明采纳协议
var texualDescription:String {
return “asdfasdf”
}
}
//空扩展体 来采纳协议
extension TextRepresentable {}

协议类型 的集合

协议的继承

协议可以继承其他的协议
就跟类一样,一个类可以继承其他的类
一个类,可以采纳其他的协议

类类型 专属 协议
protocol SomeClassOnlyProtocol : class, SomeInhreieitProtocol {
//这里是类类型 专属协议的定义部分
}

只能让类 来采纳 该协议, 结构体, 枚举 不能采纳该协议

协议合成

let adfa: protocol<somapra, anotherpro>
局部作用域有效的,临时的协议
协议合成, 协议继承 ?

函数传递过程的可选解包
可选类型 就是 类型后面加? , 或者!
参数为 一个 可选类型,或者一个语句块中定义的一个变量为 可选类型。
加!,使用变量时 会强制解包, 如果为nil则运行时错误。

如果不加?,! ,这个参数或变量,不能nil,没有初始化的值不能赋值
除非是定义为可选

所以,swift的好处是 如果一个函数, 或者闭包, 参数类型后面没有?,!不是可选的, 那么这个
参数是一定不会为nil的。因此可以放心使用

条件绑定一定要是对可选变量进行解包
把一个可选类型 -》 类型: 解包
可选类型 -》 可选类型: 不会触发解包

检查 协议一致性

is: 是否符合协议
as? 符合时,返回实例, 否则返回nil
as ! 符合时返回实例, 失败时,crash

as? , as! 强制转换以后 ,绑定到实例时,
那个实例, 仅仅是 符合 协议类型的实例, 其他的属性不可以被访问和打印

可选的 协议要求

整个函数类型是可选的, 不是函数的返回值可选
可选的协议要求 只能用在标记了@objc的协议中
@objc protocol CoutnaerDataSource {
optional func adsfa(coutn:Int)->Int
optional var fixedIncrement:Int {get}
}

协议扩展

提供默认实现

协议本身来实现功能。 协议 ,不是 一堆的 方法、属性、下标、构造 后面没有赋值,也没有花括号吗?
协议本身来实现 方法、属性、 下标、构造
protocol RandmNumberGenerator {
func rundom()->Float
}
extension RandomNumberGenerator {
func randomBool()->Bool {
return random() > 0.5
}
}
通过协议扩展, 所有采纳协议的类型, , 都能获得这个扩展所增加的方法实现。

如果 扩展的协议, 被某一个类所采纳, 这个类,自己实现了 扩展中的协议要求,
那么,它自己实现的, 将会替代扩展中的 默认实现

协议扩展 提供了默认的实现, 采纳了这种协议的类, 因为有了默认的实现, 但是它却是又 声明了,需要实现协议的要求, 然后协议所要求的 属性、 方法、 下标 都在默认中被实现了,
因此 , 这些要求 , 可以不需要类 去实现。 和 可选的协议一样:
有要求, 但是可以实现要求, 可以不实现要求,

那么区别是? 提供默认实现的协议扩展要求,和协议中声明的可选要求 ,有什么区别?
optional声明的要求:可选链式调用
在扩展中默认实现的要求:直接调用

为协议扩展添加限制条件

//where子句
extension CollectionType

where Cdfadf.element:
TextaereTalbe
{
var asdfDesrpt:String {

}

}
扩展collectiontype协议, 只适用于
集合中的元素采纳了textrepresentable协议的情况
where Generator.Element: TextRepresentable

把逻辑 和 行为 分开--》协议

值类型
String,Array和Dictionary类型均以结构体的形式实现。这意味着被赋值给新的常量或变量,或者被传入函数或方法中时,它们的值会被拷贝。

NSString,NSArray和NSDictionary类型均以类的形式实现,而并非结构体。它们在被赋值或者被传入函数或方法时,不会发生值拷贝,而是传递现有实例的引用。
闭包是引用类型

方法命名
at, in, on, during, for
over,above,below,before,after,
with, through,except, but
as for, according to along with, ashore
since,util,

“等价于”表示两个类类型(class type)的常量或者变量引用同一个类实例。
恒等

//用值类型
“等于”表示两个实例的值“相等”或“相同”,判定时要遵照设计者定义的评判标准,因此相对于“相等”来说,这是一种更加合适的叫法。

用struct,enum,tuple,string,array,dictionary
1,要用==运算符来比较实例的 数据 时
2,两个实例的拷贝 能 保持 独立的状态 时
3,数据被多个线程 使用 时
可以在线程之间安全的传递变量,而不需要特地去同步,不需要花功夫来防范其他代码在暗地里修改它们

用class
1,共享的 可变对象时
2,==来比较实例 身份的 时

参数名和类型,外部名称,内部名称

有意在初始化时设置为空的
override 重写构造器
override

required子类必须实现该构造器
父类的必要的 构造器 , 可以不需要添加override修饰符

属性

存储型属性:
常量结构体的存储型属性:无法修改该实例的任何属性
延迟存储属性
lazy:
1、实例的构造过程结束后,才会知道影响值的外部因素时,可以使用lazy
2、获得属性的初始值需要复杂 或 大量 计算时, 可以只在需要的时候计算它。

计算型属性
只读计算属性:只有getter,没有setter
必须使用var关键字定义计算属性。 包括只读计算属性。
因为他们的值不是固定的。let用来声明常量,表示初始化后,再也无法修改的值。

全局变量
在函数、方法、闭包 或 任何类型之外定义的变量

局部变量
在函数,方法,闭包内部定义的变量

类型属性

计算型类型属性,
static var adf:String{
get{return “asdf”}
set(value){afsdfa = value}
}

存储型类型属性,
staic var sdfChannles:Int = 10

只读计算型类型属性,
static var adf:String{
get{return “asdf”}
}

只读存储型类型属性:
static let asdf = 1

计算型、
存储型、
延迟存储属性、 不需要加lazy,它本身就是延迟初始化的,
什么是延迟: 在被访问的时候,才会初始化。即使是多个线程同时访问,
系统也保证对其进行一次初始化

如果是局部变量,局部的存储型属性,加了lazy,延迟存储属性,没有被初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次

观察器、
lazy延迟存储属性
计算属性本身就是延迟属性
可以为 存储属性 添加属性观察器,设置默认值时不会被触发。

不需要为 延迟存储属性添加观察器,不需要为 计算型属性添加观察器。
但是 如果 是继承过来的包括存储型 和 计算型, 可以添加观察器

默认值、

赋值语句
构造器
便利构造器
可失败构造器

继承
定义一个基类
子类生成

重写

实例方法、 类方法 都可以重写
如果不写override,编译将会不通过,报错
凡是重写的属性, 都可以提供getter,setter,或者添加willset/didset观察器
计算型必须是var,只读计算型,是只提供getter
存储型可以是let,var,只读存储型,是加let
加let的存储型属性, 子类继承它时,重写let的只读存储型属性,提供getter,setter
只要提供getter,setter,属性就不能加let关键字,也就是说 父类只读的let 存储型的属性,重写时,不能提供getter,setter
重写getter,setter, 一般是对父类的var 存储型属性、 计算型属性 进行重写

防止重写
final

存储型属性的 初始化
存储型属性的值不能处于一个未知的状态

自定义构造过程
构造参数、
可选属性: 在初始化的时后设置为空
常量属性,构造时,指定一个值. 一旦常量属性被赋值, 它将永远不可更改
常量属性,只能在 定义它的类的构造过程中修改, 不能在子类的 构造过程中修改

默认构造器
没有父类、所有属性都有默认值, 自动生成一个构造器

值类型的构造器代理
便利构造器: 就是init里面可以调用init

类 类型 : 指定构造器、 便利构造器

类的继承和构造

两段式构造?

指定构造器必须总是向上代理
便利构造器必须总是横向代理

可失败构造
init?()
return nil
init?(rawValue:){}
用一个非可失败的构造器 重写了父类的可失败构造器
感叹号! 问好?
!:对应类型的隐式解包可选类型

必要构造
隐式解包可选类型
重写父类的必要构造器时, 不需要加override

闭包或函数 设置默认值
用闭包为属性提供默认值。 没有参数的闭包
{[weak self] (dfasdf:String, asdf:Int) in
asdfasdf = asdfasdf
return asdfasdf
}()
{[weak self] in
asdfasdf = asdfasdf
return asdfasdf
}()
{[weak self]
asdfasdf = asdfasdf
return asdfasdf
}()
表示立即执行此闭包
不能在闭包里面访问其他属性。即使这些属性有默认值。 也不能使用self,
不能调用任何实例方法

!
required
用闭包为属性提供默认值 用 “ = ”
仍然是存储型属性
let add:String = {return “asdfasdf”}()

计算型属性
let add:String {get {return “11”}
set(value) {
staff = value
}}

可失败构造器
init?(asdfa:String) {
if da.isEmpty() {return nil }
self.asdfasd = asdfa
}
一旦构造失败 , 就会触发断言
init!(adfa:String){
if adfa.isempty() {return nil}
self.asdf = adfa
}

构建一个对应类型的 隐式解包可选类型 的对象。
? 可选链式调用 访问 可选字符串类型String?
自动赋值为nil
用闭包 为属性 提供默认值
闭包的 返回值 赋值
闭包本身 的 赋值
任何缺少override关键字的重写都会在编译时被诊断为错误。
使用关键字 final 来禁用子类重写
final var
final func
final class func
final subscript
防止重写
class添加final,整个类 标记 为final, 这样的类不可以被继承
你不可以将一个继承来的读写属性重写为一个只读属性。
如果你在重写属性中提供了 setter,那么你也一定要提供 getter。如果 不想写getter, 可以再getter中 ,直接返回 super.someproperty
setter > getter

可选链式调用:在当前值可能为nil的可选值上 请求和调用 属性、方法、下标的方法。
如果可选值有值,调用成功;如果可选值是nil,那么调用 将返回nil。
多个调用连接在一起,形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,整个调用链返回nil
!:强制展开,如果失败,就会crash
?:可选调用,如果失败,就会返回nil

使用?代替!
为可选链式调用 定义模型类
?访问属性
?调用方法
?访问下标
多层可选链式调用
在方法的可选 返回值 上进行可选链式调用

js.residence?.address = “asdfa”
可选链式调用失败时,等号右侧的代码不会被执行
johoo.residence?[0]

弱引用,或无主引用,以替代强引用,从而解决循环强引用的问题
var dictionary = [“dave”:[2,3123,4], “bev”:[123,3,45,1]]
dictionary[“dave”]?[0] = 123
dictionary[“bev”]?[2] = 12
dictionary[“adsfafds”]?[2] = 123

在方法的圆括号后面加上?
if let beginWithThe = joho.residence?.address?.buildingIndetifer()?.hasPrefix(“”) {
if begintWithThe {
} else {
}
}
在方法的返回值上 进行 可选链式调用, 而不是方法本身

1,弱引用, a,b 都是?可选的
一个人不总是有房子,一个房子不总是有人住在里面

2,无主引用, a必须有b,b不一定有a
一个人可能有、或者没有信用卡, 但是一张信用卡总是关联着一个客户

3,隐式解析类型, 无主引用: a,b,都不能为nil
每个国家必须有首都,每个城市必须属于一个国家
隐式解析可选类型的属性 在类型结尾处 加上感叹号City!的方式,将country的capitalCity属性声明为隐式解析可选类型的属性。 capitalcity属性的默认值为nil,但是不需要展开它的值就能访问它

Person和Apartment的例子展示了两个属性的值都允许为nil,并会潜在的产生循环强引用。这种场景最适合用弱引用来解决。

Customer和CreditCard的例子展示了一个属性的值允许为nil,而另一个属性的值不允许为nil,这也可能会产生循环强引用。这种场景最适合通过无主引用来解决。

然而,存在着第三种场景,在这种场景中,两个属性都必须有值,并且初始化完成后永远不会为nil。在这种场景中,需要一个类使用无主属性,而另外一个类使用隐式解析可选属性。

闭包引起的循环强引用问题,
解决方法,还是使用 weak, 或者 unowned
如果被捕获的引用绝对不会变为nil,应该用无主引用,而不是弱引用。

lazy属性, 只有当初始化完成 以及 self 确实存在后,才能访问lazy属性。 因此闭包中, 可以用self

闭包捕获列表 [unowned self, weak deleate = self.delegate]
某一个对象持有闭包, 闭包体里面 使用了这个对象self, 这样互相持有,两个对象就产生了循环强引用

lazy var jj:(Int,String) -> String = {
[unowned self, weak delegate = self.delegate!] (index:int, stringtoProcess: String) -> String in
闭包的函数体 语句
}

lazy var someClusre:Void -> String = {
[unowned self, weak delegate = self.delegate!] in
闭包的函数题语句
}

无主引用、
弱引用: 总是可选类型。 当引用的实例被销毁,弱引用的值会自动为nil
无主引用:同时销毁
当引用计数为0时,销毁实例
创建实例的强引用。 强: 它将实例牢牢保持住,只要强引用还在,实例是不允许被销毁的

隐式解析
显示解析?

函数, 方法 , 闭包 内部定义的变量--局部变量
全局变量, 存储型变量
延迟存储属性 lazy,
全局的变量 本来就是 延迟计算的, 不需要加lazy

先写 父类名, 在写 协议名

protocol Fullynamed {
var fullName:String {get}
}

var a = Int
var a = Double
var a = [“1”, “2121”,”12312”]
begin . . . end
var shotpis = Int
shapes[1…3] = []
var letters = Set<Int>()
var letters:Set<String>
Array<Int>()
Int
Int,String,Int
Int:String,String:Int
枚举:
关联值
原始值
成员值

枚举
枚举值
原始值: 字符串, 字符, 整型, 浮点型
初始值
关联值:
递归枚举

1,关联值 存储在枚举成员中, 2, 原始值 存储在枚举成员中,
==》 枚举值

使用整数作为原始值, 隐式赋值, 依次递增1
第一个枚举成员, 原始值 为0
使用字符串做为枚举类型的原始值时, 每个枚举值成员的隐式原始值 为 该枚举成员 的名称
使用原始值 初始化 枚举 实例
enum ad : Int{
case a, b, c , d
}
if let a = ad(rawValue:1)? {
switch a {

case .a:
case .b:
case .c:
case .d:
default:

} else {

}

oc枚举,枚举值只能是整型:int、unsigned int,long,long long、int32_t、int64_t、nsinteger
swift枚举
1、是集合类型,值类型
2、枚举成员,可以关联任意类型:string、array、int、dictionary、double、float,struct、class、元组、函数类型、闭包类型
关联值-在switch case分支中使用let或var前缀,提取每个关联值;如果一个枚举成员的所有关联值都被提取,可以把let放在成员名称前面, 括号面的每一个关联值省略let或者var
3、跟class一样,有构造方法、析构方法,还可以遵循协议
4、用在switch分支语句中,必须穷举所有枚举值
5、枚举成员不会提供默认值,本身就是完备的值:可以使用原始值填充成员
6、枚举值可以递归: 某一个成员的关联值类型是枚举类型自身,在这个成员类型的定义前面加上 indirect关键字

enum asdf{
case asdfa
case asdf2
case asdfasdf(fads:String,fadsf:int)
case asdfdf(dfad:String)
}
asdf.asdfa(“asdfas”,”asdfasdf”)
let asdff = asdf.asdfasdf(fads:“fads”,fadsf:”fsdfasdf”)
switch asdff {
dase .asdfa
case .asdf2
case .asdfasdf(let a, let b)
print (a)
print (b)
case .asdfdf(let c)
print (c)

}
元组

1,

git

//github

//gitlab

svn

try? hell()
try! hell()

throws写在箭头前面
do catch
func fudd() throws -> String{
return
}
do {
//expression: 表达式
try expression
statements
} catch pattern 1 {
//匹配模式
statements
} catch pattern 2 where condition {
statements
}
将错误转换成可选值, try?expression时, 一个错误被抛出,那么表达式的值就是nil.
下面x,y 有着等价的含义
func sometthorwingFunction() throws->String {}
let x = try? sometthorwingFunction()
let y:String?
do {
y = try sometthorwingFunction()
} catch {
y = nil
}

func fetchData()->Data?{
if let data = try ? fetchDataFromDisk() {return data}
if let data = try ? fetchDataFromServer() {return data}
return nil
}
禁用错误传递, 如果真的抛出了错误, 则会在运行时发生错误
let photo = try!loadimge(“./asdfasdf/df.jpg”)
当前作用域退出之前执行
func processFile(fileName:String)throws {
if exists(filename) {
let file = open (filename)
defer {
close(file)
}
//try? ,不需要catch。 返回nil, try!不需要catch,运行时错误 try:立即抛出一个错误
while let line = try file.readline() {

    }
}

}

如果一个或者多个条件不成立,可用 guard 语句用来退出当前作用域。
guard语句格式
guard 条件 else {
//条件 可以使用可选绑定, 条件的结果必须符合booleantype协议
语句
guard绑定的值 guard语句后面可以使用
guard let a = asfOptional else {return}
print(a)//a可以使用

//必须有else子句,而且在子句中 标记 noreturn特性的函数,或者使用return, break, continue, throw
退出作用域
}

强制展开 触发运行时错误
可选 可选链式调用
可选的
强制的
可选链式调用失败时, 后面的 调用 不会 执行
嵌套类型 加前缀 加上 外部类型的类型名作为前缀

可选链 , 强制展开
?, !
?返回nil, 可选展开
!如果是nil ,则触发 运行时 错误, 因为没有展开的值

都可以用数组字面量

1、数组字面量 创建数组
[Int]
Array<Int>()

2、集合
[1,2,3,4] 可以是数组或者集合

3、字典
字典字面量 创建字典
[Int:String]
Dictionary<Int,String>()
[“a”:”adsf”,”asdf”:”1231”]

扩展,
1, 类, 结构体, 枚举, 协议
添加新的功能

2,
计算型属性、
计算型类属性
实例方法、 类方法
新的构造器
定义 和使用 新的 嵌套类型
支持 新的 一个 或 多个 协议
mutating, 改变 实例

func dfasd(a:protocol<UITableViewDataSource, UITableViewDelegate>, b:String)
extension CollletctionType

数组的遍历

索引值 和 数据值 组成的元组
元组 分解成 临时常量 或者变量 来进行遍历
for (asdf,asdfd) in somearray.enumerate() {

}

1,闭包是引用类型
闭包 作为 参数 传递
闭包是在 函数 返回后 才被执行
从函数中逃逸

@noescape,不允许逃逸
可以使用self
闭包的生命周期 就在 函数里面。
func adf(@noescape closure()->Void){
closure()//确保在add调用后就没有用了
}

sort方法 传递 一个闭包参数, 在排序结束之后就没用了
escape允许逃逸出函数作用域
var a:[()->String] = []
func collectA(@autoclosure(escaping) pp:()->String){
//pp并没有调用, a在函数作用域范围外, 函数返回之后被调用,
允许逃逸出函数作用域
a.append(pp)
}
collectA(array.removeAtIndex(0))
collectA(array.removeAtIndex(0))
for aa in a {
aa()
}

2,自动闭包
自动创建的闭包, 用一个普通的表达式 来 代替 显示的闭包
statements 表达式 会被返回
这种闭包不接受任何参数、当它被调用的时候,会被返回被包装在其中的表达式的值。
用普通的表达式 来 代替显式的闭包,从而省略闭包的{}花括号
自动闭包的好处就是节省内存吧?
fatalError(“1g bytes”)并没有分配 1g的内容存储。其实就存储了一个闭包使用的时候才会被调用

a(“dfadf”)
等价于
a( void -> void in { return adfadf } )

显示的闭包{(params) -> returnType in statements}
in可以省略

返回类型可以省略、参数名称可以省略(使用缩写)、直接用一个运算符、
尾随闭包 可以省略小括号、

let add = {array.removeAtIndex(0)}
这个闭包 并没有执行
只有当调用 add()才会执行
延时求值
@autoclosure
() -> String
{ somefunc(asdfa) }

fatalError(@autoclosure message:()->String){}
fatalError(“HEllooooo”)

fatalError({ (Void) -> Void in “hellowoooo”})

{
(params) -> returnType in
statements
}
闭包, 根据上下文推断类型,({s1, s2 in s1 > s2})
参数重 使用参数名的缩写, 则参数可以省略, 返回类型可以省略, 直接写函数体names.sort({$0 > $1})
使用运算符函数 names.sort(>)
尾随闭包
闭包可以在被定义的上下文中, 捕获常量 或 变量
func makeIncremeter(amount:Int) -> () -> Int {
var runingttoal = 0
func incremter() -> Int {
runingttoal += amount
return runingttoal
}
return incremter
}
let a = makeIncremeter(4)
let b = makeIncremter(12)
a()
b() //12
let c = b
c() //24 函数 和 闭包 都是引用类型。

一个没有参数,并且返回值为string的函数()->String{}
let a = {
print(“adsfadsfa”)
}
//并不会打印adsfadsfa
a()
这时候打印
var cutomersInline = [“asdf”,”asdfasfd”,”asd”]
func saveCustomer(customerProvider:()->String){
customerProvider()
}
saveCustomer({customersInline.removeAtIndex(0)})

func saveCustomer(@autoclosure customerProvider:()->String){
customerProvider()
}
//自动转化为一个闭包
saveCustomer(customerInline.removeAtIndex(0))

3,@autoclosure(escaping)

{
(s1:String,s2:String) -> String in
return “asdfa”
}
闭包的写法:
1,上下文 推断 类型
{s1, s2 -> Int in return 1 }
2,单表达式隐式闭包, 省略return关键字
{s1, s2 in s1 > s2}
3,参数名称 也可以缩写
{$0 > $1}
4,>,省略了参数, 省略了返回值, 省略了return,大括号也省略了
names.sort(>)
5,{(a:String,and:Int) -> Void in print(“asdfa”)}
6,{[unowned self] (a:String,and:Int) -> Void in print(“afasdfasdfa:(self.name)”)}
尾随闭包,
函数的最后一个参数 是 闭包类型。
调用这个函数
func somefun(cll:()->Void){}
func somefun(cll:()->()){}
somefun(){}
somefun({})
somefun{}
func somefunc(s:String, ff:()->Void){}
somefunc(s:”asdfa”,{})
somefunc(s:”asdf”){}

func hell(add:String…) -> String{

}
参数是一个元组, 返回值 也是 一个元组
0个 或 多个
func hell(ads:String…) -> (asdf:String,adds:Int) {
for aasdf in ads {
}
}
一个函数 最多 只能有一个 可变参数

闭包做函数的参数
函数做函数的参数

闭包捕获列表

lazy var asdf:Void->String = {
self.name
}
lazy var asdf:Void->String = {

[unowned self, weak delegate = self.delegate!] in
这里是闭包函数题
}

func asHtml()->String{
}
a.asdf()
a.ashtml()

swift的权限控制 与 继承 无关, 是单纬度的。
因为 swift的主要需求是:将一个类、 框架 的实现细节 隔离保护起来。

1,objc的扩展和swift的扩展?
扩展: 为一个已有的类、 结构体、 枚举、 协议 添加新功能
swift的扩展没有名字
使用static 来定义类型属性。
存储型属性 不能 作为类方法, 不能用static, class
存储型类属性, 用static, 子类不能重写
计算型类属性, 用static不能重写, 用class可以重写
为类 定义 计算型 的类型属性, 可以改用关键字 class 来支持 子类对父类 的实现 进行重写。

计算型类型属性
static var add:Int {return 1}
static var ad:String = “123123”
class var add:Int {return 1}
AddClass.add = 1213
AddClass.ad = 123123

实例方法、 类方法
class func asdfa(){}
构造器
下标
可变实例方法
给self赋值
定义和使用 新的嵌套类型
扩展 符合 某个协议

2,扩展 和 继承 、扩展 ?
扩展 可以为一个类型添加新的功能, 但是不能重写已有的功能
扩展 不能 重写 已有的功能
协议
方法、 属性、下标
类、结构体、枚举 都可以采纳协议

[]
[AnyObject]
1、一个任意类型对象的数组
2、任意类 类型
3、类,枚举,结构体,函数,闭包

Any 函数类型, 非类类型

is 检查类型
as 转换类型
检查 一个 类型 是否实现了 某个协议
@objc
标记 @objc特性 的协议 , 只能 被 继承子 objc 类的子类
其它的类、结构体、枚举 不能采纳这种协议

switch表达式的case中 使用 is 和 as 操作符
Any 或 AnyObject
空的元组:(), Void

func adfMean(asdf:Double…)->Double {

}
func ad(ads:Int…) -> (a:String,b:String)? {
for str in ads {

}
if true {
return nil
}
return (“123”,”ads”)
}

默认参数值
默认值 的 参数 放在最后, 非默认参数的顺序是一致的

\0
\
\t
\n
\r
\”
`
\’
\u{222f9abcd}
Character

override
重写属性、方法、重写下标
在重写定义的前面 加上 override关键字。
重写属性观察器
计算型属性 和 和属性观察器
计算型属性不能用let
计算型属性:提供setter和getter方法。前面加var关键字
只读计算型属性:去掉setter方法,但是前面的var关键字不能省
延迟存储型属性:前面加layer
存储型属性:去掉layer
属性观察期:使用关键字willset,didset 后面 加花括号

全局变量:
var gloableString:String = "asdfadf"
只读计算型全局变量:
var gloableString2:String {
get {
return "asdfas"
}
}
var gloableString3:String = {return "asdfa"}()
不能加lazy:下面编译错误
lazy var gloabelString4:String = "asdfasdf"

class add {
let adfa:String {
return “asdfasdf”
}
}
case add {
var adfa
var ad:String {
get {
return “asdfasdf”
}
set (asdf) {
adfa = asdf
}
}
}

存储属性添加属性观察器
延迟
intrinsic

1, 函数 , 闭包 , 区别
函数作为参数传递
闭包作为参数传递?
@autoclosure 自动闭包
@noescape 非逃逸闭包

行參中的闭包默认是逃逸的:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
undefineEscapeFunc {
print("hellooo")
}
let aAction = handlers.first!
aAction()
return true
}
typealias aBlockType = ()->()
var handlers = aBlockType
func undefineEscapeFunc(a:()->()){
handlers.append(a)
}

@autoclosure(escaping)

1、为协议扩展 添加限制条件。限制条件 写在 协议名 之后, 使用where子句来描述
数组 符合 collectiontype协议, 而数组中的元素 又符合 textrepresentable协议
extension collectiontype where generator.element:textrepresentable {

}

2、类型约束
c1必须符合container协议, c2必须符合container协议,c1的itemtype 必须 和c2的itemtype类型相同]
func allitemsMatch <c1:container, c2:Container where c1.itemtype == c2.itemtype, c1.itemtype:equatable> (somecontainer:c1,_ anothercontainer:c2)->bool{
}

0..<numberOfSections

类型、表达式、语句、声明、特性、模式、范型参数

枚举
枚举关联值
枚举原始值
递归枚举:indirect
枚举 本质上 就是 用来 描述数据的。 是某种数据的 一种 描述形式,它本身不需要有计算。

空合运算符

let a:String ?
let b:String = “asdfasd”
a != nil ? a! : b
a = a ?? b

闭合区间
a…b
for index in 1…5 {
print(index)
}
半开区间
a..<b
for i in 0 ..< count {

}

func afads(numbers: double … ) -> Double {
var totoal:Double = 10
for number in numbers {
totaol += number
}
return totoal / double(numbers.count)
}

访问控制
模块 和源文件、
访问级别、
访问控制语法:public,internal,private
自定义类型:
元祖、 函数、 枚举、 嵌套
类类型:
如果想为 一个 自定义的类型, 指定访问级别
如果将类型 指定为private,那么这个类型的所有成员,都为private
如果将类型 指定为public,或者internal,或者不指定的,默认是internal,它的成员默认是internal
元祖:(var name:String, var sex:String,var idno:String) ?
(public var name:String, internal var sex:String, private var idno:String)
函数类型:
private func somefunction()->(someinternalclass, someprivateclass){}
枚举:
public enum compasspoint{
case north
case south
}
以最低级别的访问权限为准
可以通过 重写 为继承来的类成员 提供更高的访问级别。
类A 的私有成员 外部不能访问
public class A {
private func someMthoed(){}
}
类B,继承类A,可以重写类A的私有方法, 因为类B的实现跟类A在同一个源文件里面。
它把类A的私有成员拉升到高一级别的访问权限了, 给外部的文件访问类B的方法
internal class B: A {
override internal func someMthoed(){}
}

类型 变量
不能定义一个public级别的属性,但是它的类型却是private级别的 变量

getter, 和setter
stuct trackedstring {
var numberofeidits = 0
private(set) var adfa = 1
private(get) var adf = 12
}

构造器
可以低于 等于 所属类的类型 的访问级别。必要构造器 必须和所属类型的访问级别相同
默认构造器的访问级别与所属类型的访问级别相同。但是如果类型的访问级别是public,则它的默认构造器的
访问级别是internal, 如果希望默认的构造器在别的文件中使用,必须提供一个 public访问级别的
无参数构造器。

如果 结构体中的 存储型属性的访问级别是private,默认的逐一构造器的访问级别是private

协议
协议继承 不能通过继承,把原来的协议访问级别拉高
protocol asdfasd {
func adfa()
var hellor:String
let idnor:Int
}
internal protocol asdfasd {
private func adfa()
private var hellor:String
internal let idnor:Int
}
internal protocol fasdHeritProtocol:adfas {

}

类型别名

类型别名的访问级别 不可高于其他表示的类型的访问级别
private typealias helloClalss = String

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

推荐阅读更多精彩内容