swift int转string_Swift集合类型协议浅析(下)
關注【搜狐技術產品】公眾號,第一時間獲取技術干貨
導讀
本篇是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:)反射機制。
來看一個例子:
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轉換回原始類型,沒有任何信息丟失;
協議的繼承關系如上圖所示,很多系統類型已經實現了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)表示??傊?#xff0c;同樣的字母也可以用一對標量——一個標準的字母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 ?繼承關系:
所以初始化一個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實戰技巧
加入搜狐技術作者天團,千元稿費等你來!
獲取更多資訊請關注微信公眾號【搜狐技術產品】,微信后臺聯系搜狐技術產品小助手。
總結
以上是生活随笔為你收集整理的swift int转string_Swift集合类型协议浅析(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DICOM学习(3)——python实现
- 下一篇: 回文算法java实现_java算法题:最