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)//123

var num2: Int? = Int("fff")
print(num2)//nil

扩展出:

var num: Int? = "123"
print(num)//123

var 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 = 10
    var 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 = 10
    var 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 {
    //定义一个key
    private static var AGE_KEY: Bool = false
    var 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 _ = initTask
        let _ = 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 in
    return 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 in
    return i % 2 == 0
}
print(array3)
//[2, 4]

reduce

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

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

//0是初始值,第一次遍历的时候,partialResult = 0
//当第二次遍历的时候,partialResult就是partialResult + i(初始值已经没用了)
//i就是遍历的元素
var array4 = array.reduce(0) { partialResult, i in
    return 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去掉,并且将可选类型解包

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java微服务分布式事务框架seata的TCC模式

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…

蓝桥杯 EDA 组 2023模拟+真题原理图解析

本文解析了标题内的原理图蓝桥杯EDA组真题,2021-2022 省赛真题/模拟题在上一篇文中。本文中重复或者是简单的电路节约篇幅不在赘述。 其中需要补充和计算原理图的题目解析都放在最下面 一、2023 年第十四届省赛模拟题1 1.1 Type-C 接口电路 通过 CH340N 将数据转化为…

List系列集合:ArrayList、LinkedList --java学习笔记

List系列集合 特点:有序、可重复、有索引 ArrayList:有序、可重复、有索引LinkedList:有序、可重复、有索引 List集合的特有方法 List集合因为支持索引,所以多了很多与索引相关的方法,当然,Collection的…

Visual Studio 插件 AnAPI++ for VS 2022

Anmial API abbreviation AnAPIis an automatically generated WebAPI project that has encapsulated Jwt Oauth2 token authentication, SqlSugar, Swagger, Nlog, Cross domain technologies, and supports Net6 and above versions Anmial API缩写AnAPI是一个自动生成的Web…

pytest简介以及命令行执行

pytest简介以及安装 pytest简介导入第三方库修改工具类 pytest命令方式执行函数执行pytest中的参数详解 pytest简介 pytest有很多强大的插件 pytest-html (生成html格式的自动化测试报告) pytest-xdist (测试用例分布式执行,多cpu…

如何在 Odoo 17 中创建进度条

Odoo 提供各种字段小部件,例如单选按钮、浮点数、百分比、颜色选择器、复选框、状态栏和 URL。通过使用不同的渲染模板,我们可以使用小部件修改视图。它还帮助我们根据自己的需求进行设计,从而简化、加速、扩展和提高开发效率。在本博客中&am…

三分钟教会你水果音乐编曲软件 FL Studio v21.2.3 中文免费版安装方法

随着数字音乐制作的发展,音乐编曲软件已经成为音乐制作人和爱好者不可或缺的工具。FL Studio v21.2.3是一款功能强大的水果音乐编曲软件,它具有直观的界面,易于学习和使用。本文将介绍FL Studio v21.2.3的特点和优势,以及它在音乐…

cloudflare 应用例子几则

Cloudflare(以下简称 CF) 堪称互联网活菩萨,造就一大批高质量的互联网基础技术服务,更难得的是,几乎所有的服务都有对应的免费的套餐,而且出手大方,基本上有足够的容量或请求次数。 CDN CF 最…

Amazon Aurora Limitless Database :数据库管理的全新境界

在当今数亿用户、PB 级数据和数百万交易的业务环境中,数据库管理面临着巨大的挑战。传统数据库扩展的繁琐性和耗时性使得许多组织需要花费数月甚至数年的时间来构建自定义软件以满足其极端的工在当今数亿用户、PB 级数据和数百万交易的业务环境中,数据库…

美易官方:美股维持涨势,三大股指再创新高

在今日的早盘交易中,美股市场继续维持其涨势,三大股指再次刷新历史纪录。市场信心受到一系列积极经济数据的支撑,投资者对未来的经济增长和企业盈利保持乐观态度。 首先,让我们来看一下道琼斯工业平均指数的表现。该指数在早盘交易…

思科无线控制器配置学习

文章目录 简单拓扑WLC配置 简单拓扑 WLC配置 WLC#show running-config Building configuration...Current configuration : 11943 bytes ! ! Last configuration change at 16:22:44 UTC Thu Mar 14 2024 by admin ! version 17.9 service timestamps debug datetime msec se…

微信小程序开发之创建一个自己的项目和项目目录下各个文件的了解

1、小程序开发工具基础 (1)菜单栏:可以对开发工具进行一些简单的设置,还可以在帮助一行获取学习相关api文档 (2)模拟器显示栏:每当我们在进行便写好代码之后,通过编译可以在模拟显示…

运维-[frp配置内网服务器访问外网]

背景 同一局域网里面,两台服务器A服务器可以访问外网,代理端口为10809,B服务器不可访问外网 实现工具 通过frp进行内网穿透配置代理服务 配置 A服务器配置 A服务器配置frp客户端 配置文件-frpc.ini server_addr:B服务器IP server_port:B服务…

ATG-3080功率信号源的应用领域有哪些

功率信号源是一种用于提供稳定功率输出的电子设备,它在许多应用领域中发挥着重要作用。下面西安安泰将详细介绍功率信号源的几个常见应用领域。 电子测试和测量:功率信号源广泛应用于各种电子测试和测量场景。它可以提供稳定的功率输出,用于测…

六面体单元热应力问题有限元求解 | Matlab源码 | 理论文本 | 温度应力 | 热应变 |温度应变 |热力耦合

专栏导读 作者简介:工学博士,高级工程师,专注于工业软件算法研究本文已收录于专栏:《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现,并提供所有案例完整源码;2.单元…

非标图纸管理系统,非标图纸管理系统哪家好

非标图纸管理系统 是指专门用于管理非标准化设计图纸的系统。非标设计图纸是指不符合标准规范的设计图纸,可能是由于特殊需求、个性化定制或者其他原因引起的。这些非标设计图纸可能包括产品设计图、建筑设计图、工艺设计图等。非标图纸管理系统哪家好择彩虹图纸管理…

Juniper SRX 防火墙基础上网配置

简介 基于PNET-LAB模拟器,使用 vSRX-NG 23.4R1.9 镜像进行实验。 博客:https://songxwn.com/Juniper-SRX-snat/ 实验需求 配置WAN口 LAN口,实现基础的上网功能。配置NAT、DHCP。 ISP 路由器使用Cisco IOS模拟,与SRX对接口配置…

洛谷入门——P1765 手机

手机 题目描述 一般的手机的键盘是这样的: 要按出英文字母就必须要按数字键多下。例如要按出 x \tt x x 就得按 9 9 9 两下,第一下会出 w \tt w w,而第二下会把 w \tt w w 变成 x \tt x x。 0 0 0 键按一下会出一个空格。 你的任务是…

CasaOS玩客云使用Docker部署21.6K星星memos开源云笔记服务

文章目录 前言1. 使用Docker部署memos2. 注册账号与简单操作演示3. 安装cpolar内网穿透4. 创建公网地址5. 创建固定公网地址 前言 本文主要介绍如何在CasaOS玩客云,使用Docker本地部署21.6K stars的热门开源云笔记服务memos,并结合cpolar内网穿透工具打…

四十八岁男子心慌心悸,失眠,喉咙有异物,刘家峰告诉你怎么办!

植物神经功能紊乱,通常简称为植物神经紊乱,是一种涉及自主神经系统的失调疾病。自主神经系统负责控制人体内许多自动功能,如心率、血压、消化和体温调节。植物神经功能紊乱是指由于自主神经系统失衡导致的一系列症状和体征的综合症。 植物神经…