从OC到Swift的快速实践

mac2026-09-02  6

本文是参考这篇博客, 里面的内容 ,我用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 对控制器中的代码进行布局.

 

 

最新回复(0)