Swift知识点(二)


17. 字面量协议、模式匹配、条件编译

字面量(Literal)

var age = 10
var isRed = false
var name = "Jack"

上面代码中:10、false、"Jack"就是字面量

可以看到,初始化过程很简单,直接赋值即可

Swift自带的绝大部分类型,都支持直接通过字面量进行初始化

而,当是一个对象的时候,却需要使用下面方法去初始化:

var p = Person()
var p = Person.init()
问:为何自带类型可以直接初始化?而对象却不可以?

是因为Swift自带类型,遵守了对应的 字面量协议

在这里插入图片描述

var num: Int = true
当直接写上述代码时,是错误的❌
因为,把bool值类型,赋值给了int类型,类型不匹配

但,当做下列操作,即可变为编译正确

//extension扩展协议
//Int类型遵守ExpressibleByBooleanLiteral协议
extension Int: ExpressibleByBooleanLiteral{//协议要实现的方法public init(booleanLiteral value: BooleanLiteralType) {self = value ? 1 : 0}
}var num: Int = true
print(num)var num2: Int = 100
print(num2)1
100

在扩展中添加协议成员
我们可以通过扩展来扩充已存在类型( 类,结构体,枚举等)。
扩展可以为已存在的类型添加属性,方法,下标脚本,协议等成员。

其中:

//ExpressibleByBooleanLiteral是一个协议
public protocol ExpressibleByBooleanLiteral {associatedtype BooleanLiteralType : _ExpressibleByBuiltinBooleanLiteral//协议要实现的方法init(booleanLiteral value: Self.BooleanLiteralType)
}
作业:
var num: Int? = Int("123")
print(num)//123var num2: Int? = Int("fff")
print(num2)//nil

扩展出:

var num: Int? = "123"
print(num)//123var num2: Int? = "fff"
print(num2)//nil或0

参考答案:

extension Int: ExpressibleByStringLiteral
{public init(stringLiteral value: String) {self = (Int(value) != nil ? Int(value)! : 0)}
}var num: Int? = "123"
print(num)var num2: Int? = "fff"
print(num2)

模式(Pattern)

什么是模式?
模式是用于匹配的规则,比如switch的case、捕捉错误的catch、if\guard\while\for语句 的条件等

let age = 2
if case 0...9 = age {print("in")
}

相当于switch写法

switch age{case 0...9:print("in")default:break
}

也就是,if case相当于只有一个case的switch

for case let
let points = [(1, 0), (2, 1), (3, 0)]
for case let(x, 0) in points{print(x)
}
//1
//3
let ages: [Int?] = [nil, 2, 3, nil, 5]
for case let age? in ages {print(age)
}
等价于:
for item in ages {if let age = item {print(age)}
}

可以看出,可选模式(上面)的这种写法比下面的简单

表达式模式(Expression Pattern)

表达式模式用在case里面

利用这个,可以自定义case的匹配规则
比如:学生里面有score和名字,当做switch比较的时候,就可以只比较score

~= 重写模式
在这里插入图片描述

// MARK:标记
// TODO: 将要做
// FIXME: 需要修复


18. 从OC到Swift

Swift调用OC

  1. 新建一个桥接头文件,文件名格式默认为:{targetName}-Bridging-Header.h
    该文件,是OC暴露给Swift使用的
  2. {targetName}-Bridging-Header.h文件中# importOC需要暴露给Swift的内容
如果C语言暴露给Swift的函数名,跟Swift中其他函数名冲突了

可以在Swift中使用@_silgen_name修改C函数名

例如:
在这里插入图片描述

OC调用Swift

Xcode已经默认生成一个用于OC调用Swift的头文件,文件名格式是:{targetName-Swift.h}

不同于上面那种直接在.h文件中手动写导入#import 方法
OC调用Swift,不需要自己手动导入{targetName-Swift.h}
而是暴露出来,即前面加上特定关键词,系统会自动加入到{targetName-Swift.h}文件中去

swift中的class,需要暴露出来,才能被OC引用。
swift中的class继承NSOjbect,即是暴露操作

问1:为什么要暴露给OC的 Swift中的类 一定要继承NSObject?

因为是在OC里面调用,走的是runtime那一套,也就是需要isa指针,因此,在Swift中,必须使其继承NSObject

问2:OC中的方法,在Swift中去调用,比如person.run()(run方法定义在OC中),那么,此时的底层调用是OC的runtime机制?还是Swift中虚表机制?同理,在OC中调用Swift方法,比如[car run];(run方法定义在Swift中),底层调用又是如何调用的?

通过汇编打断点,可以看出
在这里插入图片描述

在Swift中调用OC的方法,还是使用的runtime那一套
在OC中调用Swift的方法函数,由于已经是继承NSObject,因此,还是走的runtime那一套

问3:在Swift中,class已经被暴露出去,那么,此时再调用已经被暴露出去的函数方法,底层又是如何呢?

(如果没暴露,调用函数方法,必定是走Swift调用那一套)

仅仅是暴露,还是在Swift中调用的话,没有走runtime那一套,走的是Swift自己虚表那一套

如果实在是想让方法走runtime那一套的话,可以在方法前加上dynamic关键字,则就走的是runtime那一套
在这里插入图片描述
以上图片方法是指:
方法一:使用@objc给每一个需要暴露的属性添加修饰
方法二:使用@objcMembers修饰类,里面所有的属性,都可以访问(不需要一个一个加)

同样,防止两个属性、类同名,也可以对Swift的调用修改名字:
@objc(name)

OC调用Swift中的#selector(方法名1)
方法名1,前面需要加@objc修饰,将其暴露出去
因为,本身#selector方法在OC中,就是runtime那些,所以在swift中需要暴露


String

  • Swift中的String与OC中的NSString可以互相桥接转换
  • String不能 桥接转换成 NSMutableString
  • NSMutableString继承NSString,因此可以 桥接转换成String

其他Siwft、OC桥接转换:
在这里插入图片描述


19. 从OC到Swift、函数式编程

问:下列p对象,占多少个字节?

class Person{var age = 10var weight = 20
}var p = Person()
//8 8 8 8
//metadata指针 引用计数相关 age weight

8个字节,是metadata指针
8个字节,是 引用计数相关
8个字节,是age
8个字节,是weight
因此,一共占32个字节

问:下列p对象继承NSObject,占多少个字节?

class Person: NSObject{var age = 10var weight = 20
}var p = Person()

8个字节,是isa指针
8个字节,是age
8个字节,是weight
字节对齐(需要是16的倍数),需要8个字节
因此,一共占32个字节

虽然都是32个字节,但是存储内容不一样

只能被class继承的协议

某个协议,只允许被class继承,不允许被struct继承,如何操作?

//定义一个协议
protocol Runnable {
}//struct遵守协议
struct Person: Runnable {}
//class遵守协议
class Student: Runnable {}

当,协议被这样修改的时候,就可以实现想要的效果:

protocol Runnable: AnyObject {}protocol Runnable: class {}@objc protocol Runnable {}

在这里插入图片描述

被@objc修饰的协议,还可以暴露给OC去遵守实现
即:OC可以调用swift中的协议方法

dynamic

被@objc dynamic修饰的内容,会具有动态性,比如走Runtime那一套流程

KVC\KVO

swift支持KVC\KVO
有几个要求:

  • 属性所在的类、监听器需要最终继承NSObject
  • 属性前加:@objc dynamic修饰

关联对象(Associated Object)

在swift中,只有Class可以使用关联对象
默认情况下,extension(扩展)是不可以添加存储属性的(可以扩展计算属性
此时,使用关联对象,就可以实现类似:类实现存储属性的效果

class Person {}extension Person {//定义一个keyprivate static var AGE_KEY: Bool = falsevar age: Int {get{//&Person.AGE_KEY 或者 &Self.AGE_KEY// Self就相当于当前类(objc_getAssociatedObject(self, &Person.AGE_KEY) as? Int) ?? 0}set{//newValue,把传进来的值存进去(10)objc_setAssociatedObject(self, &Person.AGE_KEY, newValue, .OBJC_ASSOCIATION_ASSIGN)}}
}var p = Person()
p.age = 10
print(p.age)
资源名管理

直接赋值图片名不太好,因为有一张图片,100处在用,如果现在要修改图片,则需要全局修改
可以做类似安卓的图片名赋值方式,写一个全局的名称,用的时候直接用全局字符串名,修改的时候,只需要修改一处地方即可。

多线程开发

DispatchQueue.main.async {print("主队列,异步执行")
}DispatchQueue.global().async {print(Thread.current, "全局并发队列")
}

延迟执行

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 10) {print("do something")
}

只执行一次

dispatch_once在swift中已经被废弃

可以使用lazy代替

//fileprivate只访问当前文件
//全局变量的初始化,默认也是lazy的
fileprivate var initTask: Void = {print("----init-----")
}()class ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()let _ = initTasklet _ = initTask//只会打印一次}
}

Array的常见操作

  • map
  • filter
  • reduce
  • flatMap
  • compactMap

map

map的作用:会将array里面的元素全部拿出来遍历,然后处理元素,处理完毕后再组成一个新数组array2

var array = [1, 2, 3, 4]
//map的作用:会将array里面的元素全部拿出来遍历,然后处理元素,处理完毕后再组成一个新数组array2
var array2 = array.map { i inreturn i*2
}
//或者简写
//var array2 = array.map{ $0 * 2}print(array2)
//[2, 4, 6, 8]

映射一遍,可以改变输出元素的类型,比如Int变成String

filter

filter也会遍历数组的每一个元素,但,它会有过滤的效果
array.filter(isIncluded: (Int) throws -> Bool>)
里面的返回值是Bool类型
如果是true,则放入到新数组里
如果是false,则不要

找出数组里面元素为偶数的元素,组成新数组:

var array3 = array.filter { i inreturn i % 2 == 0
}
print(array3)
//[2, 4]

reduce

reduce也会遍历array里面所有的元素
然后对元素做有关联 的操作

有关联:下次用到的数据,与上次运行的结果有关

//0是初始值,第一次遍历的时候,partialResult = 0
//当第二次遍历的时候,partialResult就是partialResult + i(初始值已经没用了)
//i就是遍历的元素
var array4 = array.reduce(0) { partialResult, i inreturn partialResult + i
}print(array4)
//10
大致过程是:
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
或者是:
((((0 + 1) + 2) + 3) + 4) = 10

reduce还可以简写:
var array4 = array.reduce(0) { $0 + $1 }

reduce就是解决:遍历数组,对里面所有元素进行有关联操作的问题

flatMap

首先,了解下Array.init(repeating: 2, count: 3)
代表,创建一个数组,数组3个元素,每个元素的值都是2

var array = [1, 2, 3]var array2 = array.map { Array.init(repeating: $0, count: $0)}
var array3 = array.flatMap { Array.init(repeating: $0, count: $0)}print(array)
print(array2)
print(array3)
打印结果:
[1, 2, 3]
[[1], [2, 2], [3, 3, 3]]
[1, 2, 2, 3, 3, 3]

也就是,flatMap会将数组里面的元素,放在新的数组里面

compactMap

var array = ["123", "test", "jack", "-30"]
var array2 = array.map{Int($0)}
var array3 = array.compactMap{Int($0)}
print(array)
print(array2)
print(array3)
打印结果:
["123", "test", "jack", "-30"]
[Optional(123), nil, nil, Optional(-30)]
[123, -30]

当使用map的时候,里面转换,有可能转换成功,也可能转换失败,因此,数组里面存放的是可选类型或nil
当使用compactMap的时候,返回结果里面会将nil去掉,并且将可选类型解包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI应用开发-基于python的知识图谱技术

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享,包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

力扣爆刷第102天之hot100五连刷96-100

力扣爆刷第102天之hot100五连刷96-100 文章目录 力扣爆刷第102天之hot100五连刷96-100一、136. 只出现一次的数字二、169. 多数元素三、75. 颜色分类四、31. 下一个排列五、287. 寻找重复数 一、136. 只出现一次的数字 题目链接:https://leetcode.cn/problems/sing…

Python PyQt5

实现界面开发,与tkinter功能一致,网上已有详细资料,此处仅记录自己的代码: 文章目录 1. 实操1.1 main.py1.2. 窗体模块代码1.3. 页面效果 2. 参考资料2.1. PyQt5 参考资料2.2. tkinter 参考资料 3. 安装注意事项3.1. 下载3.2 Pyc…

python --- 练习题3

目录 1、猜数字游戏(使用random模块完成) :继上期题目,附加 2、用户登录注册案例 3、求50~150之间的质数是那些? 4、打印输出标准水仙花数,输出这些水仙花数 5、验证:任意一个大于9的整数减去它的各位…

Blender小:图片转mesh,并展UV

其实就这么一个插件:Image2Mesh https://github.com/kedepot/i2m-std blender加载完图片之后点这个就行 到了这一步还不行如果直接放到unity中使用的话,添加材质和贴图之后每一个小块都是独立的区域来展示贴图,所以需要展UV

蓝牙HFP协议推荐的语音丢包补偿算法浮点实现的定点化

最近在做蓝牙的宽带语音通话。相对于蓝牙窄带语音,主要变化是把采样率从8k变到16k,以及编解码器从CVSD变成mSBC(modified SBC,改进的SBC)等。蓝牙语音通话相关的HFP(Hand Free Profile)强烈建议…

【随笔】Git -- 解决提交时本地与目标分支不一致导致提交失败(三)

💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…

高标准农业四情监测系统的应用范围

高标准农业四情监测系统的应用范围【TH-Q1】随着科技的不断进步,高标准农业四情监测系统已经逐渐成为现代农业的重要组成部分。这一系统能够实时监测土壤、气候、作物生长和病虫害情况,为农业生产提供精准的数据支持,从而提高农作物的产量和质…

武汉星起航引领跨境电商新潮流,一站式孵化平台助力合作伙伴腾飞

在全球经济一体化的大趋势下,跨境电商以其独特的优势逐渐成为连接各国市场的桥梁。随着市场竞争的加剧,传统的经营模式已难以满足日益复杂的业务需求,合作伙伴迫切需要更为全面、专业的指导和支持。正是在这样的背景下,武汉星起航…

读天下杂志读天下杂志社读天下编辑部2023年第51期目录

阅读星光 满树桃花开,桃李报恩来 (1) 曹万花 困境中求生,逆境中发展——《鲁滨孙漂流记》阅读感悟 (4) 车宝江 《诗经》对我国传统意境论的深化 (7) 成卓华、 《读天下》投稿:cn7kantougao163.com 英美文学作品翻译中的不对等性…

AJAX-Promise

定义 Promise对象用于表示(管理)一个异步操作的最终完成(或失败)及其结果值。 好处:1)成功和失败状态,可以关联对应处理程序 2)了解axios函数内部运作机制 3)能解决回调函数地狱问题 语法&…

[HackMyVM]靶场 Liceo

kali:192.168.56.104 靶机:192.168.56.124 端口扫描 nmap 192.168.56.124 # nmap 192.168.56.124 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-22 10:56 CST Nmap scan report for 192.168.56.124 Host is up (0.000095s latency). Not shown: 997 closed…

SAP-MM-设置字段默认值

当我们创建订单时,有些字段总是重复输入,每次值也是固定的,例如生产订单 如上图“生产工厂都是1000”如何设置成默认每次进入都是1000呢? 点击字段,F1 查看参数ID“WRK” 输入tcode:SU3 按上图维护数据100…

【云呐】设备固定资产管理系统怎么使用,有哪些功能

不同的软件和实际应用场景可能会使用设备固定资产管理系统软件。一般而言,这个软件通常包括以下功能:  用户管理:系统可以创建实时跟踪不同的用户和用户组,并设置不同的权限和访问级别。  权限设置:根据权限设置功…

c语言基础笔记(1)进制转换以及++a,a++,取地址和解引用

一进制转换 OCT - 八进制 DEC - 十进制 HEX - 十六进制 0520&#xff0c;表示八进制 0x520表示16进制 unsigned 无符号&#xff0c;只有正的 signed 有正有负数 char默认是signed 类型 #include <stdio.h>int main(void) { //字符转换成数字char a 5;int a1 a- 4…

SW工具下没有URDF

解决方案&#xff0c;下载

flask之ssti [WesternCTF2018]shrine1

打开题目 整理一下&#xff0c;代码: import flask import osapp flask.Flask(__name__) app.config[FLAG] os.environ.pop(FLAG) app.route(/)def index():return open(__file__).read()app.route(/shrine/)def shrine(shrine):def safe_jinja(s):s s.replace((, ).replac…

二、Web3 学习(区块链)

区块链基础知识 一、基础知识1. 区块链可以做什么&#xff1f;2. 区块链的三个特点 二、区块链的类型概括1. PoW2. PoS3. 私有链和联盟链 三、智能合约1. 什么是智能合约2. 如何使用智能合约 四、困境1. 三难选择的基本要素2. 这真的是一个三难选择吗? 五、比特币1. 什么是比特…

JVM面试篇

面试篇就是复习前面学的 什么是JVM 1.定义&#xff1a;JVM指的是Java虚拟机&#xff0c;本质是一个运行在计算机上的程序 2.作用&#xff1a;为了支持Java中Write Once &#xff0c;Run Anywhere 编写一次 到处运行的跨平台特性 功能&#xff1a; 1.解释和运行 2.内存管理…

《深入解析 C#》—— C# 3 部分

文章目录 第三章 C#3&#xff1a;LINQ及相关特性3.1 自动实现属性&#xff08;*&#xff09;3.2 隐式类型 var&#xff08;*&#xff09;3.3 对象和集合初始化3.3.1 对象初始化器3.3.2 集合初始化器 3.4 匿名类型3.4.1 基本语法和行为3.4.2 编译器生成类型3.4.3 匿名类型的局限…