Swift语法

private和fileprivate的区别

swift 面试题

https://blog.csdn.net/shihuboke/article/details/106388320

swift 与oC 的区别

https://www.jianshu.com/p/158d65bc281e

  • 结构体调用方法时,是直接call地址,而类实例调用方法时,则是通过偏移找到方法在vtable的位置,然后再call调用
  • 经过objc dynamic修饰的,方法调用objc_msgSend

swift onower 和weak的区别,onower什么情况下用

  • weak、unowned 都能解决循环引用的问题

  • unowned 要比weak 少一些性能消耗

  • 在生命周期中可能会变为 nil 的使用 weak,初始化赋值后再也不会变为 nil 的使用 unowned

  • 相同点: 引用对象的引用计数都不会加一,都不会对引用对象产生强引用

  • 不同点:weak的对象,在block块内再次获取的时候是可选的,可能为nil,调用属性或者方法需要加上?或者强制解析!,但是强制解析在对象已经被释放了时肯定会造成强解错误,导致程序崩溃

  • unower的对象,在block块内再次获取的时候依然是对象本身,非可选,因为一定保证在block块内再次获取的时候对象依然存在,不然调用属性或者方法肯定会造成导致程序崩溃

  • 另外,你还可以利用【生命周期】的长短去理解,即分别在什么场景下使用unowned和weak:

  • unowned所在的block的生命周期务必要比unowned修饰对象的生命周期短,即block一旦销毁了,也就不会再调用了,也就不存在修饰对象的引用问题了。

  • weak所在的block可能要比weak修饰对象的生命周期长,block被调用时,修饰对象可能已经释放掉了,此时通过修饰对象?去调用也就不会引发问题,保证程序正常运行。

什么时候使用 weak和unowned

  • Weak和unowned引用都不会增加引用计数,它们都能用于解除引用循环。
  • 在引用对象的生命周期内,如果它可能为nil,那么就用weak引用。反之,当你知道引用对象在初始化后永远都不会为nil就用unowned.

进行判断使用class_深入理解Swift中的Class和Struct

Swich

  • Switch 默认可以不写break,并不会贯穿到后面的条件
  • 使用fallthrough可以实现贯穿效果
  • switch必须要保证能处理所有情况
  • case、default后面至少要有一条语句,如果不想做任何事,加个break即可
  • switch也支持Character、String类型
  • Case 后面的条件也支持元组,区间,复合条件,值绑定

print

  • public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

inout

  • 可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值,func swapValues(_ v1: inout Int, _ v2: inout Int) {}

函数重载

  • 函数 个数 标签 类型不同(返回值类型不同不叫重载)
  • 默认参数与函数重载一起用产生歧义的时候不报错(C++ 报错)

高阶函数,返回值是函数类型的是高阶函数

  • 每一个函数都是有类型的,函数类型由形式参数类型、返回值类型组成
  • 函数类型作为函数的返回值,
  • 函数类型作为函数参数
  • 将一个接受多参数的函数变换为一系列只接受单个参数的函数,叫做柯里化
  • 像Array这样支持map运算的类型,称为函子(Functor)


    截屏2021-10-21 下午3.36.41.png
截屏2021-10-21 下午3.36.51.png

内敛函数

  • 如果开启了编译器优化(Release模式默认会开启优化),编译器会自动将某些函数变成内联函数
  • 将函数调用展开成函数体
  • 有些函数不被自动内敛(函数体较长,包含递归)
  • 永远不会被内联(即使开启了编译器优化) @inline(never) func test() {}
  • 被内联(开启了编译器优化即使过长也被内敛) @inline(__always) func test() {}
    typealias

typealias用来给类型起别名

枚举

  • 枚举有扩展

  • 关联值 将枚举的成员值跟其他类型的值关联存储在一起


    截屏2021-10-21 下午5.15.30.png
  • 原始值 注意:原始值不占用枚举变量的内存,隐式原始值如果枚举的原始值类型是Int、String,Swift会自动分配原始值,int默认0,1,String就是同名称的字符串

空合并运算符 ??

  • a ?? b
  • a 是可选项 ,b 是可选项 或者 不是可选项
  • b 跟 a 的存储类型必须相同
  • 如果 a 不为nil,就返回 a
  • 如果 a 为nil,就返回 b
  • 如果 b 不是可选项,返回 a 时会自动解包

结构体&类

  • 结构体,编译器会自动生成可以传入成员值的初始化方法,如果在定义结构体的时候自定义了初始化方法,那么编译器不会自动生成;
  • 类,编译器不会自动生成以传入成员值的初始化方法,如果定义类的时候,所有成员变量定义了初始值,那么编译器会自动生成无参的初始化方法
  • 结构体是值类型(枚举也是值类型),类是引用类型(指针类型)
    结构体定义的成员变量的值
  • 类是指针引用,栈上的指针引用堆上的实例对象;结构体是值引用(值拷贝),实例内存就在栈上

属性

  • 存储属性 :存储在实例的内存中,结构体和类可以定义存储属性,

    • 存储实例属性:可以通过实例访问,存储在每个实例的内存中
    • 存储类型属性:通过类型访问,整个程序运行过程只分配一块内存
  • 计算属性(类似于函数,有get set 方法,不占用实例内存,结构体和类枚举可以定义计算属性)

    • 计算实例属性:可以通过实例访问,存储在每个实例的内存中
    • 计算类型属性:通过类型访问,只分配一块内存


      截屏2021-10-23 下午11.47.39.png
  • inout的本质就是引用传递(地址传递)

动态类型语言

  • 运行时才做数据类型检查,在编译阶段不给变量设置任何数据类型,在第一次给变量赋值的时候,内部会记录下数据类型

静态类型语言

  • 编译时就开始做数据类型检查,变量声明的就得设置数据类型,使用之前也得声明数据类型

mutating

  • 结构体和枚举是值类型,默认情况下,值类型的属性不能被自身的实例方法修改
  • 在func关键字前加mutating可以允许这种修改行为

下标(subscript)

n 使用subscript可以给任意类型(枚举、结构体、类)增加下标功能,有些地方也翻译为:下标脚本,本质是方法,可以没有set方法,必须要get方法

继承

  • 值类型(枚举、结构体)不支持继承,只有类支持继承
  • 子类可以重写父类的下标、方法、属性,重写必须加上override关键字
  • 被class修饰的类型方法、下标,计算类型属性,允许被子类重写
  • 被static修饰的类型方法、下标,类型属性,不允许被子类重写
  • 子类可以将父类的属性(存储、计算)重写为计算属性
  • 子类不可以将父类属性重写为存储属性
  • 只能重写var属性,不能重写let属性
  • 子类重写后的属性权限 不能小于 父类属性的权限
  • 被final修饰的方法、下标、属性,禁止被重写
  • 被final修饰的类,禁止被继承

Any、AnyObject

  • Any:可以代表任意类型(枚举、结构体、类,也包括函数类型)
  • pAnyObject:可以代表任意类类型(在协议后面写上: AnyObject代表只有类能遵守这个协议),在协议后面写上: class也代表只有类能遵守这个协议

错误类型

  • Swift中可以通过Error协议自定义运行时的错误信息
  • 函数内部可以通过throw 抛出自定义errow
  • 可以使用do-catch捕捉Error
  • defer语句:用来定义以任何方式(抛错误、return等)离开代码块前必须要执行的代码
  • defer语句将延迟至当前作用域结束之前执行
  • defer语句将延迟至当前作用域结束之前执行
  • assert(断言)
  • 如果遇到严重问题,希望结束程序运行时,可以直接使用fatalError函数抛出错误(这是无法通过do-catch捕捉的错误)
  • 使用了fatalError函数,就不需要再写return, 在某些不得不实现、但不希望别人调用的方法,可以考虑内部使用fatalError函数
  • 可以使用do 实现局部作用域

闭包&自动闭包

截屏2021-11-02 下午2.50.18.png
  • 如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性
  • 尾随闭包是一个被书写在函数调用括号(后面)的闭包表达式

逃逸闭包

  • 逃逸闭包: 闭包作为函数的参数传递时,在函数体结束之后调用,就说闭包逃避了函数的作用域,这个闭包是逃逸型的闭包,使用@escaping来标注, 逃逸闭包一般会在多线程中使用
  • 非逃逸型的闭包:在函数体结束前被调用,闭包是非逃逸型的闭包。

协议

  • 只有将协议中的实例方法标记为mutating,才允许结构体、枚举的具体实现修改自身成员变量
  • 类在实现方法时不用加mutating,枚举、结构体才需要加mutating
  • 协议中还可以定义初始化器init ,非final类实现时必须加上required
  • 如果从协议实现的初始化器,刚好是重写了父类的指定初始化器 ,那么实现的时候这个初始化必须同时加required override
  • 一个协议可以继承其他协议
  • 枚举,类,类都可以遵守协议
  • 协议可以添加扩展
  • 协议扩展可以为遵守协议的类型添加实现,但它不能使协议从另一个协议扩展或继承。协议继承始终在协议声明本身指定。
  • 如果一个类型已经符合协议的所有要求,但是还未声明采用了该协议,则可以让它采用一个空扩展的协议:
  • is用来判断是否为某种类型,as用来做强制类型转换
  • 枚举结构体协议类都可以加扩展

你可能感兴趣的:(Swift语法)