18 swift OC 混合编程

表达式模式,调用了~=运算符 ,是一些复杂的情况 ,简单的没有调用

补存内容 : catch默认存在error

#warning()
// TODO:

编码习惯: xcode自己生成的类冒号跟着前面

@UIApplicationMain 就是新的入口

Swift调用OC写的东西

1 新建桥接文件 : targetName-Bridging-Header.h 就是OC暴露给swift的东西
@_silgen_name(“sum”) func malloc(v1: Int32, v2: Int) -> Int32

swift 暴露给OC的条件

  1. 继承NSObject
  2. objcMembers 或使用@objc 修饰需要暴露的成员

@objc 还能修改暴露给OC的类名的名称, 方法名

字符串处理 :

协议

  • 协议中的变量: 属性一律var
  • 协议里面要求的init 刚好是父类实现的init方法,需要required、override。required(来源于协议)和 override(来源于父类)都需要。而, 父类的必要初始化器, 子类实现的时候,可以省略override。
  • 非可失败的初始化器 : 非可失败、 !
  • 可失败: 三种可以
  • 协议组合 &
  • 类型属性必须是static
  • 遍历枚举 CaseIterable allcases
  • CustomStringConvertible description
  • any anyObject 只能被类准守
  • is 判断是否是某种类型 as ? Student 可选项 as Any
  • metadata 元类型
  • Persion.self 和堆空间的前8个字节存储一样的内容 就是元类型
  • Persion.Type
  • AnyClass = AnyObject.type

  • 类名和X.self有很多相同点,可以调用方法,不同点:X.self能赋值给变量,类名不能复制给变量。

  1. 使用元类型调用的初始化方法一定是requied的,因为你可以给元类型传递一个子类的对象,如果子类没有该初始化方法,那么就失败。为了不失败,所以标记为requied
  2. Self 应用于返回值,如果协议中定义的方法返回当前对象,在子类中就需要返回子类对象,所以使用Self

14 枚举的本质、溢出运算符

运算符重载

运算符重载: 类、结构体、枚举都可以为现有的运算符提供新的动能

运算符重载一般写在类里面 ,为了不定义实例,就能调用,定义为类型方法

static prefix func -(Int)-> Int {

}

Equatable协议
如果一个类已经有相等的方法,也要声明为准守Equatable协议,好处

明确告诉别人,我有比较功能
很多有要求Equatable协议的地方,都可以使用了
也能使用!= 运算符

对于引用类型,比较存储的地址值是否相等使用 === !==

Comparable 协议

比较的结果三种情况

自定义运算符
prefix operator
postfix operator
infix operator : 优先级组

结合性 : 多个运算符,描述先从左边开始,还是先从右边开始 ,如果没有结合性,表示不允许连续出现多个运算符
优先级 : 高于什么,低于什么
assignment : 在可选链拥有和赋值运算符有一样的优先级

扩展

不能添加存储属性: 不能改变内存结构
扩展可以给协议提供默认实现,也间接的实现了可选协议

13 汇编分析String、Array的结构

  • 0x30是数字0的ascii码
  • tag pointer 干嘛用的?直接将内容放在变量的地址中
  • rax rdx 两个寄存器存储返回值,rdi rsi rdx存储参数,可以创建一个多参数函数,验证。

长度大于0xf 的存储情况:

  1. rax 长度
  2. rdx 地址,地址-0x7ffffffffffffe0=真实存储地址

内存分布情况:

  1. 代码区
  2. 常量区
  3. 全局区
  4. 堆区
  5. 栈区

内存布局图:

  1. mach-o
  2. 运行内存
  3. 动态库

小技巧: 字符串的真实地址 : 后面的地址+0x20

小技巧:1后面跟着4个0 一般是全局区,如果不是那么一般是堆区

append干了什么事情: 变为堆空间, 跳过32字节,后面就是内容是存储的真实字符串

小小总结:

  1. 字符串长度<=0xf 字符串内容直接存储在变量的内存中
  2. 字符串的长度>0xf,字符串存放在常量区(__TEXT.cstring),地址信息存储在在变量的后8自己中,真实地址= 后面的地址+0x20
  3. append 后有大于0xf,会开辟空间

dyld_stub_binder

  1. stub 翻译为符号
  2. 动态库中的函数,加载完动态库才能知道(也就是运行的时候才知道),那么编译的时候怎么办? 放置一个占位地址,这个函数就是一个占位地址

数组的内存结构

arr占用8字节,这8字节存储着堆空间地址,堆空间结构:

  1. 引用计数
  2. 元素数量
  3. 数组容量
  4. 元素1
  5. 元素2
  6. 元素3
  7. 元素n