Swift学习笔记

defer

修饰函数内任意一段代码,调用时机;在函数中其余代码都执行完毕,函数即将结束前,可以用它在异常中进行扫尾工作,比如关闭IO流释放资源等

extension

通过增加的实例方法可以修改实例本身,如果结构体和枚举的方法要修改self或其属性,则需要使用mutating关键字标明
 扩展可以向已存在的类结构体和枚举添加新的嵌套类型
 
在结构体、枚举、或者协议中使用mutating修饰方法可以在该方法内部修改结构体,枚举,协议的属性变量
对值类型进行扩展时,可以使用mutating修饰方法,使得方法内部可以直接修改当前实例的本身
     
属性:不可以设置默认值,必须设置{get}或{get set},必须设置为var
方法:可以定义普通方法,也可以定义mutating方法,方法不能有方法体,方法的参数不能有默认值

@objc

1、selector中调用的方法需要在方法名前声明@objc,目的是允许这个函数在运行时通过Object_C的消息机制调用
2、协议的方法可选时,协议和方法前都要使用@objc声明
3、用weak修饰协议时,协议前面要加@objc声明
4、类前加上@objcMembers,那么这个类及其子类扩展里的方法都会隐士的加上@objc,如果不想加也可以用@nonobjc修饰
5、扩展前加上@objc那么里面的方法都会隐士的加上@objc

@objcMembers

在类名前面是使用objcMembers修饰,系统会在自动给这个类的所有方法添加@objc,暴露给OC

OC和Swift中字符串的区别

   OC中字符串是对象,性能略差
   Swift中字符串是结构体,性能更高
   String支持直接遍历

OC和Swift中数组的区别

   Array是一个结构体,NSArray是一个类
   Array可以存放普通类型
 
   reverse()数组倒序
   只有相同数据类型的数组才能合并

class和static的比较

class和static的相同点
   可以修饰方法,static修饰方法是静态方法,class修饰方法是类方法
   都可以修饰计算属性
   
class与static的不同点
   class不能修饰存储属性,static可以修饰存储属性,static修饰的存储属性成为静态变量(常量)
   class修饰的计算属性可以被重写,static修饰的计算属性不能被重写
   static修饰的静态方法不能被重写,class修饰的类方法可以被重写
   class修饰的类方法被重写时,可以使用static让方法变成静态方法
   class修饰静态属性被重写时可以使用static让其变为静态属性但是他的子类就不能被重写了
   class只能在类中使用,但static可以在类 结构体 和枚举中使用

值类型与引用类型

 结构体、枚举是值类型,类是引用类型
 不同于值类型,引用类型被赋值到一个常量,变量或者本身被传递到一个函数的时候,他是不会被拷贝的,而是使用同一个对某个实例的引用
 
 因为类是引用类型,可能有很多常量和变量都是引用到了同一个类的实例,有时候需要判断两个常量或变量是否引用自同一个实例,Swift提供了两个特征运算符来检查两个常量或变量是否引用相同的实例
 相同于:(===)  不同于:(!==)
 
 重写父类方法要在前面添加override,防止被重写可以使用final标记  final var  final func final class func
 
Swift中的结构体包含枚举是值类型,它在代码传递的过程中总是会被拷贝
   CGRect CGSize CGPoint

字符串 字典 数组的赋值与拷贝

Swift中String、Array、Dictionary类型是作为结构体来实现的,这意味着String、Array、Dictionary他们在赋值到一个新的常量或者变量或他们本身被传递到一个函数或者方法中的时候其实是传递了拷贝
 
OC中的NSString、NSArray、NSDictionary他们是作为类来实现的

类与结构体的对比

相同点:
        定义属性
        定义方法
        定义构造函数
        可以被扩展
        遵循协议
 
   类有而结构体没有的额外功能
        继承
        类型转换
        析构函数
        引用计数
类是引用类型  结构体是值类型

内存管理

内存有两个区域,栈区stack 和堆区heap 在Swift中值类型存放在栈区,引用类型存放在堆区

值类型,即每个实例都保持一份数据拷贝,值类型的赋值为深拷贝,即新对象和原对象是独立的

引用类型,即所有实例共享一分数据拷贝,在Swift中类和闭包都是引用类型,引用类型的赋值是浅拷贝,新对象和源对象的变量名不同但其引用指向的内存空间是一样的当对新对象操作其内部数据时,原对象也会受到影响

inout

是Swift关键字,可以放置于参数类型之前冒号之后,使用inout之后,函数体内部可以直接更改参数值,而且改变会保留
 
值类型变量作为参数传入函数,外界和函数参数的内存地址一致,函数内对参数的更改得到了保留
 
使用inout注意事项:
    使用inout关键字的函数,在调用时需要在该参数前面加上&符号
    inout 参数在传入时必须为变量,不能为常量或字面量
    inout 参数不能有默认值,不能为可变参数
    inout 参数不等同于函数的返回值,是一种使参数的作用域超出函数体的方式
    多个inout 参数不能传入同一变量,因为考入考出的顺序不定,那么最终的值也无法确定
 
inout参数的传递过程:
    1,当函数被调用时,参数值被拷贝
    2,在函数体内,被拷贝的参数修改
    3,函数返回时,被拷贝的参数值给原有的变量

闭包

 闭包能够捕获和存储定义在其上下文中的任何常量和变量,即闭合并包裹那些常量和变量
 闭包和函数一样也是引用类型,不是值类型
 
 {(parameters) -> (return type) in
   statements
 }
 
 闭包可以从上下文环境中捕获变量常量,并在自己作用域内使用
 Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数,嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量
 尾随闭包,函数的最后一个参数,网络请求的处理
 
 逃逸闭包,闭包作为一个参数传递给一个函数
 传入函数的闭包如果在函数执行之后才会被调用,那么这个闭包就叫逃逸闭包
 逃逸闭包会在函数结束后才执行,闭包可以超出函数的范围来调用
 
 一种自动创建的闭包,用于包装函数的表达式,不接受任何参数,被调用时会返回被包装在其中的表达式的值,在形式参数

Swift中解决循环引用的方式

方案一:
        使用weak ,对当前控制器使用弱引用
        因为self可能有值也可能没有值,因此weakself是一个可选类型,在真正使用时可以对weakself强制解包(强解包没有问题,因为控制器一定存在否则无法调用所在的函数)
 
方案二:
        使用[weak self] 可以写在闭包中,这样用到的self都是弱引用
 
方案三:
        使用关键字 unowned
        unowned像OC中的unsafe_unretained
        unowned表示:即使它原来的引用被释放掉了,仍然会保持对被已经释放的对象的一个无效的引用,它不能是Optional值,也不会被指向nil

 使用Codable协议,通过解码和编码实现json与model之间的互转

处理异常的三种方式

    1、do try catch方式,手动处理异常(建议使用)
    2、try? 方式,不处理异常,如果出现了异常,则返回一个nil,没有异常则返回对应的值
    3、try! 方式,告诉系统该方法没有异常,如果出现异常,会导致程序直接崩溃

typealias

是指类型别名,将一个已存在的类型名称改为其他名字
好处:很好的标示业务,而不仅仅是全篇的基本类型,方便统一类型管理
    typealias NetParams = [String: Any]//网络请求参数
    开源框架多平台统一类型,或者条件编译统一类型
 
    使用别名定义闭包,减少代码长度,方便阅读

参数的两种传递方式

1、值传递,传递的是参数的一个副本,这样在调用参数的过程中不会影响原始数据
    2、指针传递,把参数本身引用的内存地址传递过去,在调用过程中会影响原始数据
 
 在Swift众多数据类型中,只有class是指针传递,其余的如Int Float Bool Character Array Set enum struct 全都是值传递
 
 如果要实现让值传递变成指针传递,通过一个函数改变函数外部变量的值(将一个值类型以引用的方式传递),这时 Swift提供的inout关键字就可以实现
 即声明函数时,在参数前面加inout 修饰,函数内部改变外部参数时,在变量名前面使用&符号修饰表示,表明这个变量在参数内部是可以改变的(可将改变传递到原始数据)
 注意:⚠️inout修饰的参数是不能有默认值的,有范围的参数集合也不能被修饰 一个参数一旦被inout修饰了,就不能再被var和let修饰了
 
 1、监测属性,其实是给存储属性上添加的一种监测功能,willSet监测新值 didSet监测旧值
 2、如果函数的参数是inout修饰的,你如果将监控的属性传入这个函数的时候,此时会将属性的值拷贝一份,在函数调用结束之后将值新赋给属性,所以函数执行完毕会出发监测方法

你可能感兴趣的:(Swift学习笔记)