Foundation-String

最近寫完了Swift 3.0教程 ,在接下來這段時間,繼續寫Foundation 的教程,幫助大家更加深入,系統的學習Foundation 框架,可能會持續一段時間,希望有興趣的朋友加個關注!


初始化


  • 定義空字符串
 var str = String()
 var str1 = ""
  • 使用c的字符串初始化
var cString:[CChar] = [67, 97, 102, -61, -87, 0]
var str1 = String(cString: cString)
  • 使用一個字符進行初始化
var dog: Character = "??"
var str = String(dog)
  • 驗證性初始化
var validUTF8: [CChar] = [67, 97, 102, -61, 0]
let str = String(validatingUTF8: validUTF8)
print(str)

提示:

如果里面包含一個非法的編碼,初始化失敗返回nil

  • 對指定的指針數據進行指定的編碼
var validUTF8: [UInt8] = [67, 97, 102, 195, 0]
validUTF8.withUnsafeBufferPointer { ptr  in
    let s = String.decodeCString(ptr.baseAddress,as: UTF8.self,
                                      repairingInvalidCodeUnits: true)

輸出結果:

Optional(("Caf?", true))

提示:

1.使用這個方法時一定要注意字符數組元素必須為UInt8
2.參數repairingInvalidCodeUnits 設置為true的意思,表示如果出現編碼錯誤可以使用"\u{FFFD}" 進行替換,如果為false ,一旦出現錯誤的編碼,則直接返回nil


常用的方法


  • 字符串是否為空
str.isEmpty
  • 是否包含前綴
var str1 = "Ku1991Zou01Ti2Ya8"
str1.hasPrefix("Ku")
  • 獲取字符的個數
var str1 = "Ku1991Zou01Ti2Ya8"  
str1.characters.count // 18
  • 獲取不同編碼下的字節數量
 var str1 = "Ku1991Zou01Ti2Ya8我"
str1.utf8.count
str1.utf16.count
str1.unicodeScalars.count

輸出結果:

20
18
18

  • 獲取指定索引的字符
var str1 = "Ku1991Zou01Ti2Ya8我"
let index = str1.index(str1.startIndex, offsetBy: 8)
print(str1[index]) 

運行結果:

u

還有一個方法

str1.index(str1.startIndex, offsetBy: 30, limitedBy: str1.endIndex)

注意兩者的區別:

第一個方法如果索引訪問超過字符串的長度的話,系統會報錯崩潰,但是第二種不會報錯,會返回一個可選值nil

思考:如果索引時有條件的話,我們應該怎么做呢?看下面的例子

問題: 在一個字符串中找到第一個能被3整除的數字

let nums = "1,3,5,6,7,8,9"
let index = nums.characters.index { (char) -> Bool in
    if let num = Int(char.description){
        if num%3 == 0{
            return  true
        }
        return false
    }
    return  false
}
print(nums.characters[index!])
  • 判斷字符串是不是符合ascii 編碼
  let str = "werwer我"
  print(str.unicodeScalars.first?.isASCII)
  print(str.unicodeScalars.last?.isASCII)

運行結果:

true
false

  • 字符串反向輸出
 let word = "Backwards"
 for char in word.characters.reversed() {
         print(char, terminator="")
  }
 // Prints "sdrawkcaB"
  • 輸出對象的內容
class Student{
    var name = "大??"
    var age  = 23
}
let studentDescribing = String(describing: Student())
print(studentDescribing)

輸出結果:

Student

提示:

顯然這不是我們想要的結果,我們需要輸出里面屬性信息,怎么辦呢? 很簡單,按照下面的步驟做

//1.第一步 讓對象遵守協議 CustomStringConvertible
class Student:CustomStringConvertible{
    var name = "大??"
    var age  = 23
     //2.第二步實現協議
    var description: String{
        return name + "\(age)"
    }
}

運行結果

大??23

當然我們實現了CustomStringConvertible 協議也可以使用下面的方法查看對象的描述內容

// 映射
let studentReflecting = String(reflecting: Student())
//  直接輸出
print(Student())
  • 字符串的追加
var str  = "apple"
str.append("??") // 追加一個字符
str.append(",banana")// 追加一個字符串
str += "??" // 簡約寫法
str.append(contentsOf: ["1","2","3"])// 追加元素為字符串的數組
let newString = str.appending("new") // 追加一個字符串生成一個新的字符串

運行過程

"apple"
"apple??"
"apple??,banana"
"apple??,banana??"
"apple??,banana??123
"apple??,banana??123new

  • 大小寫變換
let str = "A,B,C,D,e,f,g,h"
var lowercase = str.lowercased()
var upperCase = str.uppercased()

運行:

"A,B,C,D,e,f,g,h"
"a,b,c,d,e,f,g,h"
"A,B,C,D,E,F,G,H"

  • 遍歷字符串
var  str = "??,??,??,??,??, ??,??,??"
for c in str.characters{
    print(c)
}

 for (n, c) in "Swift".characters.enumerated() {
       print("\(n): '\(c)'")
    }
   // Prints "0: 'S'"
    // Prints "1: 'w'"
    // Prints "2: 'i'"
    // Prints "3: 'f'"
    // Prints "4: 't'"
  • 將字符串進行分割
 var  str = "??,??,??,??,??, ??,??,??"
// 首先將字符串進行分割
let characters = str.characters.split { (c) -> Bool in
    c == ","
}
 // 然后進行map初始化
let array =  characters.map { (s) -> String in
    return String.init(s)
}

運行結果:

["??", "??", "??", "??", "??", " ??", "??", "??"]

由于swift強大的類型推斷能力,我們一氣呵成的寫法如下

let array = str.characters.split(whereSeparator: { $0 == "," })
.map(String.init)
  • 截取字符串的幾種方式

a.需求: 剔除掉非ascii 編碼的字符

 let favemoji = "My favorite emoji is ??"
 if let i = favemoji.utf16.index(where: { $0 >= 128 }) {
     let asciiPrefix = String(favemoji.utf16.prefix(upTo: i))
    print(asciiPrefix)
 }

運行結果:

Optional("My favorite emoji is ")

b.需求: 從第一個位置開始截取6個字符

 let favemoji = "My favorite emoji is ??"
 let startIndex = favemoji.index(favemoji.startIndex, offsetBy: 1)
 let endIndex = favemoji.index(favemoji.startIndex, offsetBy: 6)
 print(favemoji[startIndex...endIndex])

c.替換字符串中指定的字符串

 var  favemoji = "My favorite emoji is ??"
 favemoji = favemoji.replacingOccurrences(of: "My", with: "")
print(favemoji)
  • 修改字符串中的值

需求: 找出字符串中的數字放到一個新的數組中, 并從字符串中過濾掉這些數字

var str1 = "Ku1991Zou01Ti2Ya8"
let nums = str1.withMutableCharacters { (chars) -> [Int] in
 return  chars.map({ (c) -> Int? in
        if let num = Int(c.description){
           chars.remove(at:chars.index(of: c)!)
            return num
        }
        return nil
    }).filter({$0 != nil}).map({ (num) -> Int in
        return num!
    })
}

print(str1)
print(nums)

運行結果:

KuZouTiYa
[1, 9, 9, 1, 0, 1, 2, 8]

提示:

1.首先map,將數字從當前字符串中移除,如果是數字類型則返回,不是數字的字符返回nil
2.這時候,我們的數組里面的值是可選類型,我們通過filter過濾掉nil 得到沒有nil的可選值數組,此時再map一下,將可選值值編程非可選值

  • 截取字符串的寫法
let favemoji = "My favorite emoji is ??"
     if let i = favemoji.utf16.index(where: { $0 >= 128 }) {
         let asciiPrefix = String(favemoji.utf16.prefix(upTo: i))
         print(asciiPrefix)
   }

輸出:

"My favorite emoji is "

let snowy = "?? Let it snow! ??"
let nsrange = NSRange(location: 3, length: 12)
if let r = nsrange.toRange() {
let start = snowy.utf16.index(snowy.utf16.startIndex, offsetBy: r.lowerBound)
let end = snowy.utf16.index(snowy.utf16.startIndex, offsetBy: r.upperBound)
let substringRange = start..<end
print(snowy.utf16[substringRange])
}

輸出:

Let it snow!


高級方法


  • 獲取字符串指針地址
 var dog: [UInt8] = [97,98,99,100,0]
var str = String(cString:dog)
str.withCString { (ptr)  in
    // 獲取字符串的指針地址
    print(ptr)
}

運行結果:

0x00006080000498f0

一般人不知道的東西

  • 如果你初始化時使用的"cString" 包含不合法的UTF-8 編碼單元,會被系統自動替換為Unicode編碼的字符"\u{FFFD}"
var str = "\u{FFFD}"
print(str)

執行結果:

"?"

var cString:[CChar] = [67,97,102,-61,0]
var str1 = String(cString: cString)

提示:

-61 就是非法的UTF-8編碼,但是(-61,-87就是正確的編碼),代表:é

運行結果:

"Caf?"

  • 如何獲取數組的指針地址,以及如何修改指針的地址?
var validUTF8: [CChar] = [67, 97, 102, -61, -87, 0]
  validUTF8.withUnsafeBufferPointer { ptr in
    // 獲取指針的地址
    print(ptr.baseAddress!)
    // 通過指針地址初始化數組
     let s = String(cString: ptr.baseAddress!)
    print(s)
    return
}

指定結果:

0x000060800004dbe0
Café

let x = validUTF8.withUnsafeMutableBufferPointer { (ptr) -> CChar in
    //獲取指針的值
    print(ptr.baseAddress!.pointee)
    // 修改指針的地址,讓其向后移動一位
    let s = String(cString: (ptr.baseAddress?.advanced(by: 1))!)
    print(s)
    return (ptr.baseAddress?.pointee)!
}

運行結果:

afé
67

  • 輸出不同進制下的數字
var num = 10
String(num,radix:2)
String(num,radix:16,uppercase: true) //輸出大寫
String(num,radix:8)
String(num,radix:10)

運行:

"1010"
"A"
"12"
"10"

注意:

要求進制至少是2,至多36

  • 懶加載執行map, filter 等方法
 var str1 = "Ku"
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
var x = str1.characters.lazy.filter { a  in
   print("方法執行了")
  return  vowels.contains(a)}

print("哈哈")
print(String(x))

運行結果:

哈哈
方法執行了
方法執行了
方法執行了
方法執行了
u

????江湖求援:

懶加載時,閉包函數會執行四次,但在普通加載的時候,只執行兩次,具體原因不詳,如果您知道為什么會這樣,煩請留言,感激涕零??!

  • 截取指定編碼下的字符串
let hearts = "Hearts <3 ?? ??"
if let i = hearts.characters.index(of: " ") {
     // 一定要注意,這一步決定不能少
     let j = i.samePosition(in: hearts.utf8)
     // 的參數類型為 String.UTF8View.Index,所以通過上面的函數獲取到對應的索引
     print(hearts.utf8.suffix(from: j))
}

運行:

<3 ?? ??

  • 輸出流協議
struct ASCIILogger: TextOutputStream {
     mutating func write(_ string: String) {
         let ascii = string.unicodeScalars.lazy.map { scalar in
             scalar == "?" || scalar == "?"
               ? "??"
              : scalar.escaped(asASCII: true)
            
         }
         print(ascii.joined(separator: ""))
     }
 }
 let s = "Swift ? and ObjectC ?"
 print(s)

 var asciiLogger = ASCIILogger()
 print(s, to: &asciiLogger)

運行結果:

Swift ? and ObjectC ?
Swift ?? and ObjectC ??
\n

  • 比較兩個字符串指定位置字符的大小
 let s1 = "They call me 'Bell'"
 let s2 = "They call me 'Stacey'"
 print(strncmp(s1, s2, 14))
 print(strncmp(s1, s2, 15))

運行結果:

0
-17

  • 檢查字符是否在范圍內

a.第一種

 let lowercase = "a"..."z"
 print(lowercase.contains("z"))

b.更優雅的寫法

if "A"..."Z" ~= "H" {
    print("H")
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創建并操作數組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,270評論 0 4
  • __block和__weak修飾符的區別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,364評論 0 6
  • 昨天許下的諾言要實現,說說我的偶像劉若英。 說起喜歡劉若英,是感性的開始,是勇氣的開始,而真正吸引我的是什么或許這...
    秋Irene閱讀 173評論 0 0
  • 春天的風,像愛人的懷抱, 溫暖、柔和。 它輕輕地撫摸著你, 給你安慰、溫暖, 讓你沉醉、迷戀。 夏天的風,像一位摯...
    一路向前2017閱讀 228評論 2 2
  • 圭臬,讀音為guī niè,是指土圭和水臬——古代測日影、正四時和測量土地的儀器,引申為某種事物的標尺、準則和法度...
    KennyP0618閱讀 1,037評論 0 0