iOS 方便的AttributedString生成

本文提供兩種簡(jiǎn)單的AttributedString的生成方式

??iOS中的NSAttributedString一直覺(jué)得不太好用,每次要加一個(gè)稍微復(fù)雜點(diǎn)的特征字符串就很麻煩,你可能會(huì)看到這樣的代碼

let attrS = NSMutableAttributedString(string: "回憶是抓不到的月光,")
let att1 = NSAttributedString(string: "握緊就變黑暗", attributes: [.font: UIFont.systemFont(ofSize: 20), .foregroundColor: UIColor.red ])
attrS.append(att1)
attrS.append(NSAttributedString(string: ",讓虛假的背影消失于晴朗,陽(yáng)光在"))
let attch = NSTextAttachment()
attch.image = UIImage(named: "Lock")
attch.bounds = CGRect(x: 0, y: -20, width: 50, height: 50)
attrS.append(NSAttributedString(attachment: attch))
attrS.append(NSAttributedString(string: "身上流轉(zhuǎn),等所有業(yè)障被原諒"))

創(chuàng)建一個(gè)不太復(fù)雜的字符串就需要很長(zhǎng)的代碼,而且不是很直觀。

一、為NSMutableAttributedString加拓展的方式

??為了解決這個(gè)問(wèn)題,筆者試用鏈?zhǔn)秸Z(yǔ)法的方式對(duì)NSMutableAttributedString做了一個(gè)拓展,同時(shí)創(chuàng)建了一個(gè)Attributes的類(lèi)??梢允褂面?zhǔn)秸Z(yǔ)法加閉包的方式快速簡(jiǎn)單的實(shí)現(xiàn)AttributedString,用了之后會(huì)再也回不去。
這里舉個(gè)栗子,簡(jiǎn)單的方式就可以實(shí)現(xiàn)上述同樣的方式。而且一些重復(fù)的工作一句就搞定

let attr = NSMutableAttributedString()
attr.add("回憶是抓不到的月光,")
     .add("握緊就變黑暗") {$0.font(20).color(.red)}
     .add(",讓虛假的背影消失于晴朗,陽(yáng)光在")
     .addImage("Lock", CGRect(x: 0, y: -20, width: 50, height: 50))
     .add("身上流轉(zhuǎn),等所有業(yè)障被原諒")
     .add {$0.color(.blue)}//此方法只對(duì)整個(gè)字符串沒(méi)有加color特征的部分生效

主要方法下三個(gè)

/// 添加字符串并為此段添加對(duì)應(yīng)的Attribute
    /// - Parameters:
    ///   - text: 要添加的String
    ///   - arrtibutes: Attribute特征
    /// - Returns: self
    @discardableResult
    func add(_ text: String, arrtibutes: ((inout Attributes) -> ())? = nil) -> NSMutableAttributedString {
        var arrtibute = Attributes()
        arrtibutes?(&arrtibute)
        let arrStr = NSMutableAttributedString(string: text, attributes: arrtibute.attributes)
        append(arrStr)
        return self
    }
    
    
    /// 添加Attribute作用于當(dāng)前整體字符串,如果不包含傳入的attribute,則增加當(dāng)前特征
    /// - Parameter arrtibutes: Attribute的DIc
    @discardableResult
    func add(arrtibutes: (inout Attributes) -> ()) -> NSMutableAttributedString {
        let range = NSRange(string.startIndex..<string.endIndex, in: string)
        var attribute = Attributes()
        arrtibutes(&attribute)
        enumerateAttributes(in: range, options: .reverse) { (oldAttribute, range, _) in
            var newAtt = oldAttribute
            attribute.attributes.forEach { (newkey, value) in
                if !oldAttribute.keys.contains(newkey) {
                    newAtt[newkey] = value
                }
            }
            addAttributes(newAtt, range: range)
        }
        return self
    }
    
    /// 為AttributeString添加圖片
    /// - Parameters:
    ///   - name: 圖片名字
    ///   - bounds: 圖片的bounds
    /// - Returns: self
    @discardableResult
    func addImage(_ name: String, _ bounds: CGRect) -> NSMutableAttributedString {
        let attch = NSTextAttachment()
        attch.image = UIImage(named: name)
        attch.bounds = bounds
        let attchAttri = NSAttributedString(attachment: attch)
        append(attchAttri)
        return self
    }

??1.func add(_ text: String, arrtibutes: ((inout Attributes) -> ())? = nil) -> NSMutableAttributedString
此方法為基礎(chǔ)方法,添加字符串同時(shí)增加Attributes,對(duì)本段字符串生效,這里試用參數(shù)默認(rèn)值的方式,如果只是添加字符串不加特征,可以省略閉包
??2.func add(arrtibutes: (inout Attributes) -> ()) -> NSMutableAttributedString *
我們也會(huì)遇到,一段字符串,中間幾段特殊,然后其他的特征是一樣的,這就可以使用這個(gè)方法。
該方法會(huì)對(duì)當(dāng)前整體生效(調(diào)用該方法時(shí)候的字符串,不影響后序添加的字符),對(duì)已有的屬性不影響,只會(huì)為不包含當(dāng)前屬性的添加該特征
??3.
func addImage(_ name: String, _ bounds: CGRect) -> NSMutableAttributedString*
添加Image的支持
其中Attributes的類(lèi)比較簡(jiǎn)單這里就不提了,可以直接看源碼

二、使用字符串插值協(xié)議

最近又發(fā)現(xiàn)一個(gè)好玩的東西StringInterpolationProtocol,它可以讓你使用\()的方式為字符串插值
下面這種形式你應(yīng)該不陌生

let time = 10
let string = "The time is \(time)."

??使用\()的方式可以在字符串中方便的插值這個(gè)是很早就有的,而在swift5中,swift增加了StringInterpolationProtocol。這個(gè)協(xié)議允許你來(lái)以自己的方式來(lái)實(shí)現(xiàn)字符串插值。這就為特征字符串的生成方式提供了新的可能,這里不再詳細(xì)介紹協(xié)議的用法,主要說(shuō)說(shuō)如何用來(lái)做特征字符串的實(shí)現(xiàn),我們先來(lái)看結(jié)果:

//一行太長(zhǎng)這里用回車(chē)做了分隔,實(shí)際是一句代碼
let str: AttributedString = "\("回憶", .weithtFont(20, .semibold), .color(.cyan), .stroke(.blue, 3))是抓不到的月光,
\("握緊就變黑暗", .font(20), .color(.red), .paragraphStyle{$0.alignment(.center)}, .strike(.black, .double)),讓
\("虛假", .font(20), .kern(5), .obliqueness(-0.2), .color(.orange))的背影消失于
\("晴朗", .font(20), .underline(.blue, .double)),陽(yáng)光在
\(image: UIImage(named: "Lock"), bounds: CGRect(x: 0, y: -20, width: 50, height: 50))
身上流轉(zhuǎn),等所有業(yè)障被原諒"
效果.png

這里AttributedString是自己創(chuàng)建的類(lèi),主要方法是下面兩個(gè)

    func appendInterpolation(_ string: String, _ attributes: AttributedString.Attributes...) {
        var attr = [NSAttributedString.Key : Any]()
        attributes.forEach { attr.merge($0.attributes, uniquingKeysWith: {$1})}
        let astr = NSAttributedString(string: string, attributes: attr)
        self.attributedString.append(astr)
    }

    func appendInterpolation(image: UIImage?, bounds: CGRect) {
        let attch = NSTextAttachment()
        attch.image = image
        attch.bounds = bounds
        let attchAttri = NSAttributedString(attachment: attch)
        self.attributedString.append(attchAttri)
    }

appendInterpolation 也是這個(gè)協(xié)議中最主要的方法,每次有\(zhòng)()的時(shí)候就會(huì)走進(jìn)你定定義的方法。后面的Attributes也是自定義的新的類(lèi),用來(lái)添加Attribtue這里使用了可變形參函數(shù),可以傳入多個(gè)Attributes
具體代碼邏輯可以看這里

關(guān)于StringInterpolationProtocolSwift中有詳盡的描述和例子,可以參考代碼和文檔理解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,200評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容