NSRange轉(zhuǎn)Range 以及Unicode字符串轉(zhuǎn)換

后臺(tái)的接口因?yàn)樾枰嫒軯S,對(duì)返回的JSON做了UrlDecode
UrlDecode嘛,很簡(jiǎn)單的啦~
只需要調(diào)用removingPercentEncoding就可以了,于是就很高興地開始敲代碼。然而事情并沒有這么簡(jiǎn)單,調(diào)用removingPercentEncoding一直返回nil,才發(fā)現(xiàn)后臺(tái)返回的串它竟然是這樣的:
%7B%22IsOK%22%3A%20false%2C%22Message%22%3A%20%22%u8BF7%u4F20%u5165%u767B%u5F55%u7C7B%u578B%22%2C%22RowCount%22%3A0%7D
看清楚,里面有部分與眾不同 ...%u8BF7%u4F20%u5165%u767B%u5F55%u7C7B%u578B... 這個(gè)是Unicode的編碼格式,然而其他部分卻是UTF8,這是什么鬼啊摔!為什么跟說(shuō)好的不一樣啊摔!還能不能愉快地敲代碼了啊摔??! (╯‵□′)╯︵┻━┻
按理來(lái)說(shuō)應(yīng)該找后臺(tái)溝通協(xié)調(diào),告訴對(duì)方:你這里代碼有問題啊?。〉抢碇歉嬖V我

萬(wàn)一被后臺(tái)妹紙打了會(huì)很沒面子 —— 百里瀲長(zhǎng)

好吧,走投無(wú)路之下又沒發(fā)現(xiàn)什么好方法可以直接轉(zhuǎn)換同時(shí)有兩種編碼格式的字符串,所以只能自己動(dòng)手,豐衣足食了

思路很簡(jiǎn)單:提取出UTF8中Unicode部分,單獨(dú)進(jìn)行解碼再合并


  1. 我們使用正則查找原串中Unicode格式的字符
var originallyString = "%7B%22IsOK%22%3A%20false%2C%22Message%22%3A%20%22%u8BF7%u4F20%u5165%u767B%u5F55%u7C7B%u578B%22%2C%22RowCount%22%3A0%7D"
let pattern = "%[uU].{4}"http://以u(píng)或U開頭的四個(gè)任意字符
let regu = try? NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive)
let matches = regu?.matches(in: originallyString, options: [], range: NSMakeRange(0, (originallyString as NSString).length))

看這個(gè)NSxxxx就該知道這里正則使用的NSRegularExpression是OC的東西,獲取到的是NSRange,而Swift3中查找需要使用Range<String.Index>我們需要先進(jìn)行NSRange轉(zhuǎn)Range<String.Index>,再找到需要轉(zhuǎn)化的Unicode串
添加一個(gè)NSRange轉(zhuǎn)Range<String.Index>extension方便使用

extension String {
    func range(from nsRange: NSRange) -> Range<String.Index>? {
        guard
            let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
            let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex),
            let from = String.Index(from16, within: self),
            let to = String.Index(to16, within: self)
        else { return nil }
        return from..<to
    }
}

挑選出所有Unicode子串

var subs:[String] = []
 for matche:NSTextCheckingResult in matches! {
       let range:Range<String.Index> = originallyString.range(from: matche.range)!
       subs.append(originallyString.substring(with: range))
}
print("Subs : \(subs)")//這樣就得到需要轉(zhuǎn)換的坑爹Unicode部分了
  1. 將Unicode字符串轉(zhuǎn)換為UTF8編碼替換進(jìn)原串中
    這里的Unicode并不是指字符串是Unicode編碼格式,而是指UTF8格式的字符串的內(nèi)容是Unicode編碼,有沒覺得繞?反正就是不能用常規(guī)的數(shù)據(jù)解碼來(lái)做就是了,不說(shuō)了,小二,上代碼!
for sub in subs {
        var sub1 = sub.replacingOccurrences(of: "u", with: "U").replacingOccurrences(of: "%", with: "\\")
        sub1.insert("\"", at: sub1.startIndex)
        sub1.insert("\"", at: sub1.endIndex)
        let data = sub1.data(using: String.Encoding.utf8)
        let encodeStr = try? PropertyListSerialization.propertyList(from: data!, options: PropertyListSerialization.ReadOptions.mutableContainers, format: nil) as! String
        let uf8DicodeStr = encodeStr?.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics)
            
        originallyString = originallyString.replacingOccurrences(of: sub, with: uf8DicodeStr!)
        print("\(originallyString)")
        //得到全部由UTF8編碼組成的字符串 
        //%7B%22IsOK%22%3A%20false%2C%22Message%22%3A%20%22%E8%AF%B7%E4%BC%A0%E5%85%A5%E7%99%BB%E5%BD%95%E7%B1%BB%E5%9E%8B%22%2C%22RowCount%22%3A0%7D
}
  1. 將去除了Unicode的純UTF8格式的Decode進(jìn)行解碼
    繞了那么大一圈,我們終于去除了坑爹的Unicode部分,最后我們愉快地調(diào)用removingPercentEncoding進(jìn)行解碼
let value = originallyString.removingPercentEncoding
print("\(value)")
//打印出 "{\"IsOK\": false,\"Message\": \"請(qǐng)傳入登錄類型\",\"RowCount\":0}"

這又是什么鬼啊摔!! (╯‵□′)╯︵┻━┻

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在當(dāng)前這個(gè)時(shí)代(比如說(shuō)公元2016年),如果你并不是在維護(hù)歷史遺留的文本處理代碼,沒有在每個(gè)地方都使用Unicod...
    縱橫而樂閱讀 2,844評(píng)論 3 16
  • 1 .字符串字面量 String 在Swift中字符串字面量是由雙引號(hào)" " 包裹著的 像我們?cè)?Swift 3 ...
    iceMaple閱讀 1,218評(píng)論 1 2
  • 首先要明白,說(shuō)服一個(gè)人是多么困難,以及這背后的原因。 美國(guó)有一個(gè)名叫“文化認(rèn)識(shí)項(xiàng)目”(簡(jiǎn)稱CCP)的研究小組,小組...
    三七悅讀閱讀 260評(píng)論 0 0
  • 喧鬧的街頭 無(wú)數(shù)擦肩而過的身影 我的出現(xiàn)會(huì)不會(huì)給你帶來(lái)一絲絲的安慰 原來(lái)我們的回憶還可以組成一個(gè)完整的故事 原來(lái)留...
    秦雨希閱讀 384評(píng)論 0 0

友情鏈接更多精彩內(nèi)容