本文是参考这篇博客, 里面的内容 ,我用playground实践了一遍,记录自己的理解和思考.
一. 数据
swift是数据安全类型, 不存在隐式转换.
类型转换标识符:
is: 一个实例是否是某一种类型
as: 将实例转换成某一种类型(子类型 -> 父类型)
as?: 将某个类型转成可选类型, 通过判断可选类型是否有值,来决定是否转化成功
as!: 转成具体的类型,如果不是该类型会crash. 强制转换
可选与非可选数据类型:
Swift, 变量没有默认值; 要么有值,要么没有值,叫做可选类型. 表示数据的状态,而不是具体的值.
结构体:
//结构体 struct HGStruct { var name: String? var desc: String? func desFunc() -> Void { //进行了强制解包 print(name! + "_" + desc!) } } //无参 构造函数 var st = HGStruct() //逐一构造函数 st = HGStruct(name: "hello", desc: "") //调用结构体函数 st.desFunc()只要结构体有属性, 默认有两个构造函数:
1. 无参构造函数
2. 逐一构造函数: 将所有的属性作为参数的构造函数. 不用func修饰, 函数名统一为init.
除去默认的,可以自定义构造函数. 此函数不需要func关键字, 一旦有自定义构造函数,默认生成的构造函数都将失效:
由于结构是值类型, 所以无法直接修改自己的值.需要使用关键字
//值类型,无法修改内部的值, 需加关键字 mutating func update(name: String) { self.name = name }枚举
//枚举 enum HGEnum: String { case go = "go_value" case back = "back_value" //枚举函数 func enumFunc() { print(self.rawValue, "指明枚举类型,就可以枚举绑定原始值") } } func direction(d: HGEnum) -> Void { switch d { case .go: print("go") default: print("back") } } print(HGEnum.go)二: 函数
//创建了一个Person类, 自定了一个构造函数 class Person: NSObject { var name: String var age: Int //构造函数 init(name: String, age: Int) { self.name = name self.age = age super.init() } }
函数重载:
1.函数名相同,参数名,参数类型,参数个数不同
2. 不仅仅局限于构造函数
重载可以快速为方法添加新的属性,属性可以通过外部传入
//函数重载 class Student: Person { var lesson: String init(name: String, age: Int, lesson: String) { self.lesson = lesson super.init(name: name, age: age) } } let s = Student(name: "Joyce", age: 13, lesson: "python)重写:
重写只能在内部设置属性,外部无法直观看到类的参数列表
子类中定义一个与父类中方法同名同参数列表的方法
//通过重写方法添加lesson属性 class Student: Person { var lesson: String override init(name: String, age: Int) { lesson = "python" super.init(name: name, age: age) } } let s = Student(name: "Joyce", age: 13)三: 类
1. 创建一个类的实例,必须在创建之后, 里面所有的非可选项属性必须有值,否则报错
class HGPerson { var name: String = "" } let p = HGPerson().name print(p)特殊方法: 构造方法 函数名统一为init
虚构函数: 实例销毁时系统调用的函数deinit,功能和dealloc一样
setter和getter方法:
var doSoemthing: String { set { } get { return "这里必须给个值" } }去掉set, 属性为只读.
属性监听
class HGPerson { var name: String = "" var sex: String = "" { willSet(newValue) { print("将改变 当前的值 = " + self.sex + ",之前的值") } didSet(oldValue) { print("改变后 当前的值 = " + self.sex + ",之前的值") } } } let p = HGPerson() p.sex = "女性"注意: 构造方法中赋值不会引起属性监视器调用
四: 协议
1. 没有继承,只能使用在没有继承NSObject的Class中, 不能使用weak修饰. weak只能修饰clas
2. 继承于class, 适用于所有class
3. 继承于NSObjectProtocol,使用所有class. 与2的区别,此协议自带了很多的系统协议. 此种不适用在没有继承NSObject的class中中,因为在swift中所有的协议函数都是强制必须要实现的
1 适合用于在于结构体和枚举中.
2适合用于没有继承于NSObject的class中
3适用于继承于NSObject的class中
delegate 仍使用weak修饰
五 泛型
函数中使用泛型
//泛型 func num<T>(a:T) -> T{ return a } let var_int = num(a: 1) let var_double = num(a: 1.1)泛型函数使用了"占位符"类型名,而不是"实际类型名","占位符"并不关心"T"具体类型,要求a和b必须是相同类型. 实际类型是由每次调用函数时决定的
在协议中使用泛型
关联类型为协议中的某个类型提供了一个占位符名称,其代表的实际类型在协议被遵循时才会制定.关联类型通过associatedtype关键字制定.
// 此 协议定义两个功能, 凡是遵守此此协议的必须实现这两个功能 //return T 表示了返回的是遵循的这个协议的类? protocol Animal { associatedtype T func run() -> T func music() -> T } class person: Animal { func run() -> person { print("Person-run") return self } func music() -> person { print("Person - music") return self } } class Pig: Animal { func run() -> Pig { print("pig - run") return self } func music() -> Pig { print("pig - music") return self } } let p1 = person() //链式调用 p1.run().music()
指定泛型的类型
//指定了泛型的类型 func funDefine<T>(a:T) where T:Pig { } //报错 Cannot convert value of type 'person.Type' to expected argument type 'Pig' funDefine(a: person) funDefine(a: BigPig())逃逸闭包
func taoyi(block:@escaping ()-> Void) -> Void { //在swift,在闭包使用闭包的情况下,想要延长其引用的闭包,那么需要将此闭包声明成逃逸闭包 let q = DispatchQueue(label: "label") let time = DispatchTime.now() + DispatchTimeInterval.seconds(2) q.asyncAfter(deadline: time) { block() } } taoyi { print("逃逸闭包在这里执行 等同于oc的block") } //闭包作为参数传入函数中, 在函数执行完之后,才执行.
使用extensions 对控制器中的代码进行布局.
