swift int转string_Swift集合类型协议浅析(下)

v2-86666d8851efe3e5991dc1d33fe8b3f8_1440w.jpg?source=172ae18b

关注【搜狐技术产品】公众号,第一时间获取技术干货

导读

本篇是Swift集合类型协议浅析系列文章的下篇,在这篇文章中,我们将继续围绕集合类型协议展开讨论,侧重点更多地关注于String相关的周边协议。

StringProtocol

代表一个字符串,这个字符串是由字符构成的集合,StringProtocol协议抽象了字符串的使用场景,比如uppercased()、lowercased()、comparable和collection等。在标准库中,只有String和SubString类型遵循StringProtocol协议,可以直接使用==对SubString和String进行判断,不需要类型转换。

1let helloSwift = "Hello Swift"
2let swift = helloSwift[helloSwift.index(helloSwift.startIndex, offsetBy: 6)...]
3
4// comparing a substring to a string
5swift == "Swift"  // true

也可以遍历substring,或者从substring截取子字符串。在标准库里也有一小部分函数使用StringProtocol类型作为参数。比如把一个字符串转换为整型就是:init(text: StringProtocol)。虽然你可能不关心是string和substring,但是使用StringProtocol作为参数类型,调用者就不用进行类型转换,对他们会友好很多。

CustomStringConvertible & CustomDebugStringConvertible

使用文本方式打印输出对象是一个常见场景,Swift提供了多种方式:

  • print使用String(describing:)初始化;
  • debugPrint使用String(reflecting:);
  • dump使用Mirror(reflecting:)反射机制。

v2-452e04f0a10d0c15236198197d07c100_b.jpg

来看一个例子:

 1struct BankCard {2    let bankName: String3    let cardNumber: Int4}5let bankcard = BankCard(bankName: "CBC",cardNumber: 123232324565)6// BankCard(bankName: "CBC", cardNumber: 123232324565)78extension BankCard: CustomStringConvertible {9    var description: String {
10        return "(self.bankName) (self.cardNumber)"
11    }
12}
13print(bankcard)
14// CBC 123232324565
1extension BankCard: CustomDebugStringConvertible {
2    var debugDescription: String {
3        return """
4        BankName: (self.bankName)
5        CardNumber: (self.cardNumber)
6        """
7} }

dump

 1func dump<T>(_ value: T, name: String? = nil, indent: Int = 0, maxDepth: Int = .max, maxItems: Int = .max) -> T23/* * - T:是要打印的参数,是一个范型,也就是支持输出各种类型 45* - name: 默认是空白,如果加上则会在打印内容前加入这个name67* - indent:缩进,默认是0,如果设置则会向前缩进相应的空白 89* - maxDepth:最大深度,默认全部打印,可以根据层级需要设置这个参数 
10
11* - maxItems:最大条数,默认是全部打印,如果需要限制内容,可以设置这个参数
12
13 */
 1let names = ["apple", "orange", "banana"]2dump(names)34print(names)56let iPhones = ["iPhoneX": 9688, "iPhone8 plus": 7888, "iphone8": 6888]7dump(iPhones)89//输出
10/*
11▿ 3 elements
12  - "apple"
13  - "orange"
14  - "banana"
15["apple", "orange", "banana"]
16▿ 3 key/value pairs
17  ▿ (2 elements)
18    - key: "iPhoneX"
19    - value: 9688
20  ▿ (2 elements)
21    - key: "iPhone8 plus"
22    - value: 7888
23  ▿ (2 elements)
24    - key: "iphone8"
25    - value: 6888
26*/
  • 打印log的时候,可以取代print,打印更详细的内容;
  • 需要在控制台打印数组或者字典的时候,用dump输出的东西更立体,不会像print一样打印出来是一行,对于特别大的数组或者字典很好用;
  • debug的时候能直接打印出对象的信息,我们debug的时候常常会打断点,然后查看对象里的参数的值,用dump相当于把参数的那个界面全部展开并打印到了控制台上。

LosslessStringConvertible

遵循此协议的类型,可以被转换为String,同时与此相反,可以再从String转换回原始类型,没有任何信息丢失;

v2-29fdf1c9ba24a17b702fd0cdcced0f82_b.jpg

协议的继承关系如上图所示,很多系统类型已经实现了LosslessStringConvertible,所以才能与String之间互相转换,如Int、Int8、Int32、Int64、Bool、Character、Double、Float等。

遵循协议需要实现init?(_ description: String)和description。

 1extension FlightCode: LosslessStringConvertible {2    public init?(_ description: String) {3        let components = description.split(separator: " ")4        guard components.count == 2,5            let airlineCode = components.first,6            let number = components.last,7            let flightNumber = Int(number)8        else {9            return nil
10        }
11        self.airlineCode = String(airlineCode)
12        self.flightNumber = flightNumber
13    }
14}
15let flight = FlightCode(airlineCode: "AA",
16                        flightNumber: 1)
17
18String(flight)
19// "AA 1"
20
21FlightCode(String(flight))
22// FlightCode(airlineCode: "AA", flightNumber: 1)

ExpressibleByUnicodeScalarLiteral,ExpressibleByExtendedGraphemeClusterLiteral,ExpressibleByStringLiteral

String字面量使用引号表示,当封闭的值包含单个字符集群时,同样的语法也可以表示字符集群文字;当封闭的值包含单个字符值时,同样的语法也可以表示Unicode标量文字。

1// ExpressibleByUnicodeScalarLiteral 
2let unicodeScalar: Unicode.Scalar = "A"
3
4// ExpressibleByExtendedGraphemeClusterLiteral 
5let character: Character = "A"
6
7// ExpressibleByStringLiteral 
8let string: String = "A"

可扩展的字形集群

每一个Swift的Character类型实例都表示了单一的扩展字形集群。扩展字形集群是一个或者多个有序的Unicode标量(当组合起来时)产生的单个人类可读字符。举例来说,字母é以单个Unicode标量é(LATIN SMALL LETTER E WITH ACUTE,或者U+00E9)表示。总之,同样的字母也可以用一对标量——一个标准的字母e(LATINSMALL LETTER E,或者说U+0065),以及COMBINING ACUTE ACCENT标量(U+0301)表示。COMBINING ACUTE ACCENT标量会以图形方式应用到它前边的标量上,当Unicode文本渲染系统渲染时,就会把e转换为é来输出。

在这两种情况中,字母é都会作为单独的Swift Character值以扩展字形集群来表示。在前者中,集群包含了一个单独的标量;后者,则是两个标量的集群。

1let eAcute: Character = "u{E9}" // é
2let combinedEAcute: Character = "u{65}u{301}" // e followed by 
3// eAcute is é, combinedEAcute is é

扩展字形集群是一种非常灵活的把各种复杂脚本字符作为单一Character值来表示的方法。比如说韩文字母中的音节能被表示为复合和分解序列两种,这两种表示在Swift中都完全合格于单一Character值:

1let precomposed: Character = "u{D55C}" // 한
2let decomposed: Character = "u{1112}u{1161}u{11AB}" // ᄒ, ᅡ, ᆫ
3// precomposed is 한, decomposed is 한

继承关系:

v2-051553f9d4cb9788dffe2369961208f9_b.jpg

所以初始化一个Unicode.Scalar通过包含多个scalar标量的字面量,或者多个字符字面量期望转成一个字符,都会失败。

1("ABC" as Unicode.Scalar) // Error
2("ABC" as Character) // Error

通过字面量初始化特定类型

 1extension URL: ExpressibleByStringLiteral {2    public init(stringLiteral value: String) {3        guard let url = URL(string: "(value)") else {4            preconditionFailure("This url: (value) is not invalid")5        }6        self = url7    }8}9
10let url:URL = "https://www.baidu.com"
11
12print(url)
13
14//let urls = URL.init(string: "https://www.baidu.com")

上面这个例子扩展了URL类型,使其能够直接通过String字面量转换为URL,十分简洁,但是这种方式也有其弊端,开发中容易引起歧义。

ExpressibleByStringInterpolation

字符串插值是Swift5的新特性;通常,字符串文字中的内插值被转换为字符串,使用String(describing:);通过遵循ExpressibleBy

StringInterpolation协议(这个协议继承ExpressibleByStringLiteral),这个类型可以定义StringInterpolation通过字面量改变插值行为。

ExpressibleByStringLiteral

三个方法需要实现:

1init(stringLiteral value: String)
2init(extendedGraphemeClusterLiteral value: String)
3init(unicodeScalarLiteral value: String)

ExpressibleByStringInterpolation

1init(stringInterpolation: StringInterpolation)

要让一个类型遵循ExpressibleByStringInterpolation,最基本的你需要:

  • 让这个类型拥有一个类型为StringInterpolation的子类型,这个子类型遵循StringInterpolationProtocol并将负责解释插值;
  • 这个子类型仅需要实现appendLiteral(_ literal: String)方法,再选择一个或多个你自己想要支持的appendInterpolation(...)签名的方法;
  • 这个StringInterpolation子类型会作为“构造器”服务于你的主类型,然后编译器会调用那些append…方法一步一步地构造对象;
  • 然后你的主类型需要实现init(stringInterpolation: StringInterpolation),它会用上一步的结果来实例化它自己。

你可以实现任何你喜欢的appenInterpolation(...)方法,这意味着你可以任意选择支持什么插值。这是一个带来巨大的可能性的超强功能。

举个例子,如果你实现了func appendInterpolation(_ string: String, pad: Int),那么意味着你将可以用类似这样的插值:"Hello (name, pad: 10), how are you?"来构造你的类型。插值只需要匹配你的StringInterpolation子类型其中一个支持的appendInterpolation方法签名。

参考:

[1].https://swift.gg/2019/04/22/swift5-stringinterpolation-part1/

[2].https://academy.realm.io/cn/posts/try-swift-soroush-khanlou-sequence-collection/

[3].https://swift.gg/2017/02/20/why-is-dictionary-not-a-mutablecollection/


狐友技术团队其他精彩文章

Swift集合类型协议浅析(上)

分布式追踪系统概述及主流开源系统对比

不了解GIF的加载原理?看我就够了!

安卓系统权限,你真的了解吗?

Swift之Codable实战技巧


加入搜狐技术作者天团,千元稿费等你来!

获取更多资讯请关注微信公众号【搜狐技术产品】,微信后台联系搜狐技术产品小助手。

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

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

相关文章

oracle视图执行脚本,Sh脚本中查询Oracle v$视图时需要在$号前加转义符“\”

DBA经常会部署一些sh脚本登陆Oracle数据库查询v$动态视图得到一些东西来实际管理自动化的目的&#xff0c;但在sh脚本中写ORACLE SQL语句时&#xff0c;如果语句查询v$视图&#xff0c;直接写v$XXXX是不能成功的&#xff0c;shell会将$当成一个参数来处理。以下面一段简单的sh脚…

微信小程序页面跳转与返回并回传数据

2019独角兽企业重金招聘Python工程师标准>>> A页面&#xff1a; .wxml文件 <view class"flex-wrp"><text style"width: 32%;">选择城市</text><input style"width: 68%;" type"text" bindtap"ci…

地址栏 输入 参数 刷新参数丢失_小米11 Pro屏幕参数曝光:2K屏幕+120Hz刷新率

本周一&#xff0c;高通已经宣布将于12月初举行的骁龙技术峰会上正式发布新一代旗舰处理器——骁龙875。根据此前的曝光消息&#xff0c;小米11系列将首发搭载这颗芯片&#xff0c;网上也已经开始对这款新机进行曝光。日前&#xff0c;海外知名论坛XDA在MIUI 12的代码中发现了一…

Cypress EZ-USB FX3 DMA模式下的串口通讯

由于公司设备升级后出了问题&#xff0c;需要对USB驱动进行修改&#xff0c;原本使用的是寄存器模式进行UART传输&#xff0c;但是由于FX3寄存器模式会出现长时间延时等待的问题&#xff0c;不得不对其传输模式进行修改。虽然赛普拉斯的EZ-USB FX3系列芯片功能强大&#xff0c;…

springboot md5加密_实在!基于Springboot和WebScoket,写了一个在线聊天小程序

基于Springboot和WebScoket写的一个在线聊天小程序(好几天没有写东西了&#xff0c;也没有去练手了&#xff0c;就看了看这个。。。)项目说明此项目为一个聊天的小demo&#xff0c;采用springbootwebsocketvue开发。其中有一个接口为添加好友接口&#xff0c;添加好友会判断是否…

suse 启动oracle11g,SuSe10下Oracle11g文件系统模式安装及配置、网络配置与连接

SuSe10下Oracle11g文件系统模式安装及配置、网络配置与连接概述本课程主要讲解oracle数据库软件的安装及配置&#xff0c;以及数据库的创建过程和网络配置与连接等&#xff1b;同时讲解一些数据库安装过程中的常见问题解决办法。注意&#xff1a;本文当中引用的package_name均为…

Python pyenv

一、简介 一般在操作系统中我们会安装多个Python版本&#xff0c;所以在进行Python版本切换时会比较麻烦&#xff0c;pyenv就提供了一种简单的方式&#xff0c;能简易地在多个Python版本中进行切换的工具&#xff0c;它简单而优雅。pyenv有以下功能&#xff1a; 1&#xff09;进…

oracle 增加间隔分区,oracle分区表之间隔分区(oracle 11g) - 漫兮网

范围分区允许用户根据分区键列值的范围创建分区。下面是一个按范围分区表的示例&#xff1a;create table sales6(sales_id number,sales_dt date)partition by range (sales_dt)(partition p0701 values less than (to_date(2007-02-01,yyyy-mm-dd)),partition p0702 values l…

c++ try catch语句_再问你一遍,你真的了解try..catch(finally)吗???

定义首先来看下 MDN 的定义&#xff1a;The try...catch statement marks a block of statements to try and specifies a response should an exception be thrown.try...catch语句标记要执行的语句&#xff0c;并指定一个当有异常抛出时候的响应简短的一句的确描述了try...ca…

lamp架构,搭建一个网络平台

首先更改主机名和 hosts 安装软件包&#xff0c;设置启动服务 设置数据库密码 上传discuz论坛包 将discuz注册的用户名写在mariadb数据库中 解压discuz包 unzip discuz包 -d /var/www/html cd到upload下 cp -rf * /var/www/html 进入数据库 mysql -uroot -p create database…

MyEclipse中SVN的使用方法

1、 加载插件 svn-myeclipse插件site-1.10.2.zip&#xff0c;解压缩后&#xff0c;将文件夹下的所有文件拷贝到MyEclipse安装包下的MyEclipse 8.5\dropins文件夹下&#xff0c;然后重新打开myeclipse&#xff0c;会弹出一个报错窗口&#xff0c;不要管它&#xff0c;关闭后&…

oracle数据泵导出csv文件,数据泵expdp导出遇到ORA-01555和ORA-22924问题的分析和处理...

使用数据泵导出数据库数据时&#xff0c;发现如下错误提示&#xff1a;ORA-31693: Table data object "CAMS_CORE"."BP_EXCEPTION_LOG" failed to load/unload and is being skipped due to error:ORA-02354: error in exporting/importing dataORA-01555:…

Go程序开发---Go环境配置:CentOS6.5+Go1.8标准包安装

1.Go安装 1.1Go的三种安装方式 Go有多种安装方式&#xff0c;可以选择自己习惯的方式进行&#xff0c;这里介绍三种安装方式&#xff1a; 1&#xff09;Go源码安装 2&#xff09;Go标准包安装 3&#xff09;第三方工具安装 这里主要介绍下Go标准包在CentOS6.5系统中的安装方式 …

python矩阵乘法_鱼书——第一章 Python入门

one 第一章1.1 Python是什么Python是一个简单、易读、易记的编程语言&#xff0c;而且是开源的&#xff0c;可以免费地自由使用。Python可以用类似英语的语法编写程序&#xff0c;编译起来也不费力&#xff0c;因此我们可以很轻松地使用Python。特别是对首次接触编程的人士来说…

keepalived vip ping不通_【干货分享】OpenStack LVS负载均衡为什么不通?

背景介绍OpenStack环境Neutron 的安全组会向虚拟机默认添加 anti-spoof 的规则&#xff0c;将保证虚拟机只能发出&#xff0f;接收以本机Port为原地址或目的地址(IP、MAC)的流量&#xff0c;提高了云的安全性。但是LVS等需要绑定VIP的场景&#xff0c;默认流量是被拦截的。需要…

Docker安装ssh,supervisor等基础工具

2019独角兽企业重金招聘Python工程师标准>>> Docker安装ssh&#xff0c;supervisor等基础工具 需要提前下载好官方的ubuntu镜像&#xff0c;我这里使用的是ubuntu:14.04版本&#xff0c;这里安装了一些基础的工具ssh&#xff0c;curl&#xff0c;wget&#xff0c;vi…

nginx集群_windows环境下搭建简单Nginx+Tomcat集群

通俗点将&#xff0c;负载均衡就是因为访问流量太大&#xff0c;导致项目访问不流畅、甚至宕掉&#xff0c;所以通过一种分流的方式来缓解这种情况。一、 工具nginx-1.8.0apache-tomcat-6.0.33二、 目标实现高性能负载均衡的Tomcat集群&#xff1a;三、 步骤1、首先下载Nginx&a…

颜色传感器TCS230及颜色识别电路(转)

摘要 TCS230是美国TAOS公司生产的一种可编程彩色光到频率的传感器。该传感器具有分辨率高、可编程的颜色选择与输出定标、单电源供电等特点&#xff1b;输出为数字量&#xff0c;可直接与微处理器连接。文中主要介绍TCS230的原理和应用&#xff0c;以及色光和白平衡的知识&…

mysql命令行导入和导出数据

首先打开命令窗口,输入命令:mysql -h localhost -u selffabu -p 连接成功后,进行下面的操作 MySQL中导出CSV格式数据的SQL语句样本如下&#xff1a; Sql代码select * from test_info into outfile /tmp/test.csv fields terminated by , optionally enclosed by " esc…

7.组件连线(贝塞尔曲线)--从零起步实现基于Html5的WEB设计器Jquery插件(含源码)...

上节讲到如何创建组件&#xff0c;清除设计器视图&#xff0c;以及设计视图的持久化和恢复&#xff0c;本节将重点讲如何实现组件间的连线&#xff0c;前面章节有提到为了方便从持久化文件中恢复&#xff0c;组件和连线是分别存放的&#xff1a;nodes和lines对象&#xff0c;两…