iOS - YYKit 之 YYText

本文只是讓自己加深下理解,方便以后查看,原作者看到有不合適的地方,或者大神們看到有不對(duì)的地方希望指正 ~

原文地址,尊重原作者 ~

<br />

一. 特點(diǎn)和用法

關(guān)于YYText的特點(diǎn)和用法請(qǐng)看@ibireme大神的github

二. 使用到的組件

  1. 介紹YYLabel之前先說一下YYTextAttribute,因?yàn)楹竺鏁?huì)大量的使用到它搜囱。
    YYTextAttribute

  2. 定義的一些Enum报账,
    YYTextAttributeType: attribute的類型伟葫,有NoneUIKit占拍、CoreTextYYText四種類型桨螺;
    YYTextLineStyleline的樣式;
    YYTextVerticalAlignment: 垂直方向text的位置藻烤;
    YYTextDirectiontext的位置;
    YYTextTruncationTypetext截?cái)嗟奈恢谩?/p>

  3. YYText中定義的Attribute Name头滔。主要是獨(dú)有的一些類型隐绵。

  4. YYTextBackedString:可以將一些表情圖片映射成純文本。

  5. YYTextBinding:使一些特定的字符串綁定在一起拙毫,YYTextView在選擇和編輯他們的時(shí)候把他們當(dāng)成一個(gè)單獨(dú)的字符。

  6. YYTextShadow:用處和NSShadow一樣棺禾,只是比NSShadow多了一些功能缀蹄,比如說可以使用blendMode(圖形混合模式)、可以在shadow上再加一層shadow膘婶。關(guān)于blendMode的學(xué)習(xí)缺前,可以參見喵神的博客

  7. YYTextDecoration:實(shí)現(xiàn)下劃線(underline)和中間截線(strikethrough)時(shí)使用,線條的形式給出了幾種樣式悬襟,可以通過YYTextLineStyle枚舉查看衅码。具體是underline還是strikethrough是在NSAttributedString+YYText中NSMutableAttributeString(YYText)中實(shí)現(xiàn)的方法。

  8. YYTextBorder:實(shí)現(xiàn)在文本周圍畫一個(gè)border脊岳,也可以是填充一個(gè)背景色逝段。

  9. YYTextAttachment:封裝需要放入text中的對(duì)象。在說明文檔中提到割捅,如果attachmentUIImage奶躯,就繪制到CGContext,如果是UIView或者CALayer就加入到text container的view或者layer中亿驾。

  10. YYTextHightlight:當(dāng)YYLabel或者YYTextView中的text可以被用戶按下時(shí)嘹黔,被按下的text會(huì)有一個(gè)highlighted 狀態(tài),這時(shí)候就需要是用YYTextHighlight來修改原來的text莫瞬。所以這個(gè)對(duì)象和YYText一樣儡蔓,只是是在highlight狀態(tài)下的YYText,而且添加了點(diǎn)擊和長(zhǎng)按事件疼邀。

  11. 再來說一下NSAttributedString+YYText文件
    在這個(gè)分類中主要是實(shí)現(xiàn)了幾類的操作:

  12. 一些操作當(dāng)前attributed string的方法
    比如說歸檔和反歸檔當(dāng)前字符串喂江、獲得某個(gè)位置的attributes、字間距檩小、色值开呐、背景色烟勋、shadow等等。具體的參見文件筐付,基本上是作者封裝的方便獲得各種數(shù)據(jù)的方法卵惦。(和Foundation比強(qiáng)大太多了)。

  13. YYText創(chuàng)建attachment的方法

  14. YYText添加YYText特有的attribute的方法

  15. 添加像設(shè)置屬性一樣的設(shè)置character attribute的font瓦戚、color沮尿、backgroundColor等等的方法

  16. 添加像設(shè)置屬性一樣的設(shè)置paragraph attribute的方法。

  17. 添加像設(shè)置屬性一樣的設(shè)置YYText attribute的方法较解。

  18. 使用range設(shè)置不連續(xù)的attribute的方法

  19. 設(shè)置text highlight的便捷方法

  20. 和其他的工具型的方法畜疾。

  21. NSParagraphStyle+YYText文件
    提供了CoreText中的CTParagraphStyleRefNSParagraphStyle之間的轉(zhuǎn)化

  22. YYTextParser
    這是一個(gè)protocol,聲明了一個(gè)-(BOOL)parseText:(NSMutableAttributedString *)string selectedRange:(NSRangePointer)selectedRange;方法印衔。這個(gè)方式是遵守這個(gè)協(xié)議必須實(shí)現(xiàn)的方法啡捶,當(dāng)YYTextView或者YYLabel中的text改變時(shí)被調(diào)用。返回YES說明修改了這個(gè)text奸焙。
    作者簡(jiǎn)單的實(shí)現(xiàn)了MarkdownParserEmotionParser瞎暑,兩個(gè)原理都差不多一樣,在這里只對(duì)EmotionParser做一下簡(jiǎn)單的介紹与帆,希望能有所啟發(fā):


    這段代碼(上圖)就是生成正則表達(dá)式_regex和映射的字典_mapper,第一層for是獲得你要匹配的key了赌,第二層是如果有這些特殊的字符需要轉(zhuǎn)譯一下,然后將這些需要比配的key 用“|”連接起來玄糟。

    這個(gè)(上圖)就是修改text之后會(huì)被調(diào)用的方法勿她,在這個(gè)方法里對(duì)輸入的text進(jìn)行匹配,如果匹配到之前_mapper中需要替換的字符阵翎,就將這個(gè)字符串替換為需要替換的表情符逢并。

    替換成表情符之后就需要重新計(jì)算這個(gè)表情符所占的range了,這個(gè)方法就是拿到替換之后的的range贮喧。

5.YYTextLayout

先看一下文檔中的說明筒狠,如下圖:


是不是很眼熟?好像在哪見過箱沦?是的辩恼,就是NSLayoutManager和NSTextContainer。他們的作用都是相似的谓形。

  1. YYTextContainer
    支持矩形(CGSize)和圖形(UIBezierPath)來初始化YYTextContainer;
    在這里重點(diǎn)說一下YYTextLinePositionModifier灶伊,它是 一個(gè)協(xié)議,定義了一個(gè)必須實(shí)現(xiàn)的方法寒跳,這個(gè)方法將會(huì)在layout完成的時(shí)候被調(diào)用聘萨,三個(gè)參數(shù)分別是存放YYTextLine的數(shù)組、完整的textlayout container童太。
    YYTextLine:它是封裝了CTLineRef的對(duì)象米辐,封裝了每一行text的具體展示位置胸完、range、這一行擁有的attachments等等翘贮,只有一個(gè)類方法的初始化方法赊窥。如果不了解一些自行描述集的內(nèi)容,對(duì)textLine中的一些屬性和操作會(huì)不是很清晰狸页,看下圖:


    邊框(Bounding Box):一個(gè)假想的邊框锨能,盡可能地容納整個(gè)字形。
    基線(Baseline):一條假想的參照線芍耘,以此為基礎(chǔ)進(jìn)行字形的渲染址遇。一般來說是一條橫線。
    基礎(chǔ)原點(diǎn)(Origin):基線上最左側(cè)的點(diǎn)斋竞。
    行間距(Leading):行與行之間的間距倔约。
    字間距(Kerning):字與字之間的距離,為了排版的美觀坝初,并不是所有的字形之間的距離都是一致的跺株,但是這個(gè)基本步影響到我們的文字排版。
    上行高度(Ascent)和下行高度(Decent):一個(gè)字形最高點(diǎn)和最低點(diǎn)到基線的距離脖卖,所以行高就是ascent + decent
    看完上面的簡(jiǎn)單介紹你就能明白巧颈,在YYTextLinesetCTLine中的代碼邏輯是從CTLineRef中取出對(duì)應(yīng)的行寬畦木、上行高度、下行高度砸泛、行間距十籍、rangge和第一個(gè)字型符的位置(這個(gè)在垂直布局會(huì)用到)。之后調(diào)用reloadBounds方法唇礁,重新計(jì)算當(dāng)前行的bounds勾栗、attachments所在的rangerect
  2. YYTextLayout
    這個(gè)真的是核心內(nèi)容了盏筐,這個(gè)文件一共3300多行的代碼围俘,從代碼量上就能看出它的地位。這個(gè)類中存儲(chǔ)著 textlayout結(jié)果琢融,所有的property都是readonly的界牡。實(shí)現(xiàn)的接口有:
    1、通過一些類方法初始化的方法(YYTextContainer漾抬、CGSizetext
    2宿亡、layout之后的attributes,都是只讀的
    3纳令、從layout中讀取信息(位置挽荠、range等等)
    4克胳、繪制text layout
    這個(gè)類主要是使用上面講過的所有的數(shù)據(jù)來繪制text,這部分的代碼還是需要一點(diǎn)一點(diǎn)的去讀的圈匆,如果是新手每一行都會(huì)有收獲(比如說我)漠另,如果是老司機(jī)就沒有必要一行行的讀了,了解他的解題思路和解決這個(gè)問題的辦法就可以臭脓。下面說一下生成layout的那個(gè)500行代碼的情況酗钞,就按照代碼的順序從上往下大概的說明一下干了什么。
* 1)来累、初始化一系列使用到的變量

2)砚作、安全判斷,textcontainer
3)嘹锁、判斷是否需要修復(fù)emoji的bug(iOS8.3中)
4)葫录、判斷是否設(shè)置了path屬性和exclusionPaths數(shù)組,做相應(yīng)的計(jì)算拿到CGPath领猾,如果CGPath為空則goto fail 返回nil(如果設(shè)置了path米同,sizeinsets就沒有用了)
5)、判斷是不是奇偶填充摔竿,判斷pathWidth是否為0面粮,判斷是否是垂直展示
6)、使用text創(chuàng)建CTFramesetterRef继低,創(chuàng)建失敗goto fail
7)熬苍、使用上一步中創(chuàng)建的frameSetter創(chuàng)建CTFrameRef
8)、從CTFrameRef的對(duì)象中獲得每一行袁翁、ctRun數(shù)組柴底,計(jì)算每一行的frame,判斷是否實(shí)現(xiàn)了linePositionModifier這個(gè)協(xié)議粱胜,有的話調(diào)用協(xié)議方法柄驻。
9)、計(jì)算bounding size
10)焙压、判斷是否需要truncation鸿脓,和按那種方式處理
11)、判斷是否垂直布局text涯曲,需要的話答憔,旋轉(zhuǎn)布局
12)、判斷得到的visibleRange長(zhǎng)度掀抹,有效的話遍歷text中的attributes虐拓,配置對(duì)應(yīng)的layout屬性
13)、配置layout中attachments
14)傲武、配置結(jié)束蓉驹,返回layout
繪制時(shí)就是根據(jù)layout中的配置情況繪制相應(yīng)的特征城榛,這段代碼在此就不做分析了。

6.YYAsyncLayer文件

YYAsyncLayerDispalyTask是在YYAsyncLayerbackground queue渲染是調(diào)用的對(duì)象态兴,它有三個(gè)回調(diào)狠持,一個(gè)willDisplay在渲染之前、一個(gè)didDisplay在渲染之后和渲染時(shí)被調(diào)用的display瞻润。

YYAsyncLayerCAlayer的子類喘垂,當(dāng)這個(gè)layer更新contents時(shí)就會(huì)調(diào)用delegate方法去調(diào)用async display taskbackground queue 渲染。這個(gè)delegate方法是YYAsyncLayerDelegate的方法绍撞。

YYAsyncLayer刷新時(shí)調(diào)用_displayAsync:方法正勒,然后調(diào)用遵守YYAsyncLayerDelegate的對(duì)象實(shí)現(xiàn)的newAsyncDisplayTask方法,獲取到需要繪制的前后和繪制時(shí)的task傻铣,根據(jù)是夠需要異步來判斷直接在主線程執(zhí)行繪制代碼還是異步執(zhí)行繪制代碼章贞。

在異步繪制過程中用到了一個(gè)異步隊(duì)列,獲取方法是YYAsyncLayerGetDisplayQueue非洲,在這個(gè)方法中有一個(gè)關(guān)于QOS的概念鸭限,NSQualityOfService(QOS) ios8之后提供的新功能,這個(gè)枚舉值是要告訴操作系統(tǒng)我們?cè)谶M(jìn)行什么樣的工作两踏,讓系統(tǒng)能通過合理的資源控制來最高效的執(zhí)行任務(wù)代碼败京,主要涉及CPU調(diào)度、IO優(yōu)先級(jí)梦染、任務(wù)運(yùn)行在哪個(gè)線程以及運(yùn)行的順序等等喧枷。

枚舉值的含義如下

NSQualityOfServiceUserInteractive 與用戶交互的任務(wù),這些任務(wù)通常跟UI級(jí)別的刷新相關(guān)弓坞,比如動(dòng)畫,這些任務(wù)需要在一瞬間完成

NSQualityOfServiceUserInitiated 由用戶發(fā)起的并且需要立即得到結(jié)果的任務(wù)车荔,比如滑動(dòng)scroll view時(shí)去加載數(shù)據(jù)用于后續(xù)cell的顯示渡冻,這些任務(wù)通常跟后續(xù)的用戶交互相關(guān),在幾秒或者更短的時(shí)間內(nèi)完成

NSQualityOfServiceUtility 一些可能需要花點(diǎn)時(shí)間的任務(wù)忧便,這些任務(wù)不需要馬上返回結(jié)果族吻,比如下載的任務(wù),這些任務(wù)可能花費(fèi)幾秒或者幾分鐘的時(shí)間

NSQualityOfServiceBackground 這些任務(wù)對(duì)用戶不可見珠增,比如后臺(tái)進(jìn)行備份的操作超歌,這些任務(wù)可能需要較長(zhǎng)的時(shí)間,幾分鐘甚至幾個(gè)小時(shí)

NSQualityOfServiceDefault 優(yōu)先級(jí)介于user-initiated 和 utility蒂教,當(dāng)沒有 QoS信息時(shí)默認(rèn)使用巍举,開發(fā)者不應(yīng)該使用這個(gè)值來設(shè)置自己的任務(wù)

Qos和GCD queue的對(duì)照?qǐng)D:


看詳細(xì)的分析請(qǐng)點(diǎn)這里

收獲到的小知識(shí)點(diǎn)

  1. iOS7 and later,UIFontCTFontReftoll-free bridged的凝垛,在iOS6懊悯,UIFont是對(duì)CTFontRref的封裝蜓谋,所以在CoreText中是可以使用UIFont的,但是在UILabelUITextView中不能使用CTFontRef炭分。
  2. NSParagraphStype不是toll-free bridged 到CTParagraphStypeRef桃焕,CoreText可以同時(shí)使用兩者,但UILabelUITextView只能使用NSParagraphStyle捧毛。
  3. 查看.a靜態(tài)文件支持哪種iOS處理器
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末观堂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子呀忧,更是在濱河造成了極大的恐慌师痕,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荐虐,死亡現(xiàn)場(chǎng)離奇詭異七兜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)福扬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門腕铸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人铛碑,你說我怎么就攤上這事狠裹。” “怎么了汽烦?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵涛菠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我撇吞,道長(zhǎng)俗冻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任牍颈,我火速辦了婚禮迄薄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煮岁。我一直安慰自己讥蔽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布画机。 她就那樣靜靜地躺著冶伞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪步氏。 梳的紋絲不亂的頭發(fā)上响禽,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼金抡。 笑死瀑焦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梗肝。 我是一名探鬼主播榛瓮,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼巫击!你這毒婦竟也來了禀晓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤坝锰,失蹤者是張志新(化名)和其女友劉穎粹懒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顷级,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凫乖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弓颈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帽芽。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖翔冀,靈堂內(nèi)的尸體忽然破棺而出导街,到底是詐尸還是另有隱情,我是刑警寧澤纤子,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布搬瑰,位于F島的核電站,受9級(jí)特大地震影響控硼,放射性物質(zhì)發(fā)生泄漏泽论。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一卡乾、第九天 我趴在偏房一處隱蔽的房頂上張望翼悴。 院中可真熱鬧,春花似錦说订、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至毯辅,卻和暖如春埂伦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背思恐。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工沾谜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膊毁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓基跑,卻偏偏與公主長(zhǎng)得像婚温,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子媳否,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

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

  • YYKit之YYText 轉(zhuǎn)載鏈接: http://www.cnblogs.com/lujianwenance/p...
    kakukeme閱讀 4,595評(píng)論 3 51
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,336評(píng)論 25 707
  • 內(nèi)容來自于 iOS文檔中 About Text Handling in iOS 部分 ios平臺(tái)提供了顯示及編輯文...
    縱橫而樂閱讀 6,788評(píng)論 2 21
  • 練習(xí)新聞聽力不能著急,用心去體會(huì)單詞
    班克西閱讀 145評(píng)論 0 0
  • 爸 媽 我近視了 一副又一副眼鏡 太陽穴被壓得不行 你們給我指的路還是看不清 好幾次我摘下眼鏡 就像個(gè)瞎子 無法前行
    小年糕菌閱讀 137評(píng)論 0 0