你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> iOS開發–從TQRichTextViewDemo中學會分析工程

iOS開發–從TQRichTextViewDemo中學會分析工程

編輯:關於IOS

 

 

1.首先找到AppDelegate類,無論一個工程有多麼復雜,多麼多的類,但入口只有一個就是AppDelegate類的didFinishLaunchingWithOptions方法。我們閱讀別人源代碼的時候可以從這裡入手。在TQRichTextViewDemo工程中,這個方法中僅創建了一個TQViewController並設置為window的rootViewController。

 

2.去看TQViewController的實現。首先也是從初始化方法開始,沒有initWithNib,那麼就看viewDidLoad。在這個方法中,只創建了一個TQRichTextView,設置了frame,text,backgroundColor,delegate等屬性,然後添加到了self.view上。看完viewDidLoad方法,發現這是系統調用的最後一個方法,那麼結合模擬器的運行效果,我們可以猜測,文字的解析和繪制過程被封裝到了TQRichTextView中。

 

3.去看TQRichTextView。

  • 浏覽一下頭文件,了解有哪幾個屬性和可調用的方法。
  • 閱讀initWithFrame方法,發現這裡只是對幾個屬性的初始化。
  • 尋找是否有重寫的set,get方法。發現setText,setFont,setTextColor,setLineSpacing方法。閱讀發現,每次更新完值後會調用setNeedsDisplay方法。說明,每次對這四個對象賦值後都會調用drawRect。
  • 繼續閱讀.m文件,發現drawRect方法,這個也是有系統調用的,那麼繪制的工作應該是在這裡完成。閱讀drawRect方法。
    1. 在drawRect中首先調用了analyzeText方法,傳入了參數_text,並把返回值賦給了_textAnalyzed。
      1. 去看analyzeText方法。首先清空了數組和字典,然後定義了一個NSString類型的result變量和NSMutableArray類型的array並賦值為richTextRunsArray。
      2. 執行TQRichTextEmojiRun的一個方法,傳入string和array的指針。
        1. 因為這個方法是TQRichTextEmojiRun的類方法,所有我們直接去看該方法,而不用去看TQRichTextEmojiRun的初始化方法。連蒙帶猜的我們可以確定這個方法應該是解析字符串中表情的方法。看重點,發現如果解析到表情,那麼就創建一個TQRichTextEmojiRun的隊形,range=表情字符串在string中的range,originalText=表情字符串,把這個創建的對象放入傳進來的數組指針中,最後替換傳入字符串中的表情字符串為空格,並返回被替換過表情的字符串。
        2. 通過看TQRichTextEmojiRun的init方法,發現初始化時設置了兩個變量,來自父類TQRichTextBaseRun,分別設置了TQRichTextRunType和是否響應觸摸。發現TQRichTextURLRun也繼承自TQRichTextBaseRun。
        3. 跳出這個方法,回到analyzeText中,繼續往下看。
        4. 執行TQRichTextURLRun的一個方法,傳入result和array的指針。
          1. 同上,直接去看這個方法的實現。從和TQRichTextEmojiRun的命名格式類似,調用的方法名類似,我們可以猜測這個方法是解析URL的,那麼就直接看重點。發現,如果找到匹配的字符串,就創建一個TQRichTextURLRun的對象,設置range=URL的range,originText = URL,然後把對象添加到傳進來的數組中,最後返回string。
          2. 通過看TQRichTextURLRun的init方法,發現同上初始化時設置了兩個變量,來自父類TQRichTextBaseRun,分別設置了TQRichTextRunType和是否響應觸摸。發現TQRichTextEmojiRun繼承自TQRichTextImageRun,TQRichTextImageRun繼承自TQRichTextBaseRun。
          3. 跳出這個方法,回到analyzeText中,繼續往下看。
          4. 遍歷richTextRunsArray中的對象,每個對象調用setOriginalFont方法,傳入參數self.font。通過閱讀上面的兩個方法的內部實現明白richTextRunsArray中保存的是TQRichTextEmojiRun和TQRichTextURLRun對象,所以去看這兩個對象的setOriginalFont方法。
            1. 這個設置的是繼承自父類TQRichTextBaseRun的屬性。
            2. 回到analyzeText繼續往下看。
            3. 返回result,跳出這個方法,繼續看drawRect。
            4. 接下來是創建NSAttrbutedString,並賦值一些屬性。
            5. 文本處理,遍歷richTextRunsArray中的對象,每個對象調用replaceTextWithAttributedString方法。
              1. 在TQRichTextEmojiRun沒有找到replaceTextWithAttributedString方法,那就去TQRichTextImageRun中找,閱讀該方法。
                1. 傳入的attrString刪除占位的空格字符。
                2. 創建CTRunDelegateCallbacks,返現設定的寬高為OriginalFont的高度的1.1倍。
                3. 創建空格NSAttrbutedString對象,添加CTRunDelegateRef屬性。
                4. 把空格NSAttrbutedString對象插入至傳入的attrString。
                5. 查看super方法,發現在這段range上還設置了一個鍵值對,key為TQRichTextAttribute,value為自己。
                6. 同上閱讀TQRichTextURLRun的replaceTextWithAttributedString方法。
                  1. 為該段range的文字添加藍色字體。
                  2. 調用super方法,為該段range添加同上的key-value鍵值對。
                  3. 返回繼續閱讀drawRect。
                  4. 下面是繪制的准備工作,不想研究咋繪制的粗讀就行。
                  5. 清空richTextRunRectDic
                  6. 繪制,不想研究的也可粗讀略過。
                  7. 找重點,繪制替換過的特殊文本單元。
                    1. 遍歷取出每一個run,取出run的attributes中key為TQRichTextAttribute的值。
                    2. 如果值存在,則說明,這個run是特殊的run。
                    3. 求run的frame,粗讀略過。
                    4. 調用drawRunWithRect方法,並將返回值賦給idDraw變量。
                      1. TQRichTextEmojiRun的drawRunWithRect方法中繪制了表情圖片,返回YES。
                      2. TQRichTextURLRun的drawRunWithRect方法返回NO。
                      3. TQRichTextBaseRun的drawRunWithRect方法返回NO。
                      4. 判斷run的isResponseTouch屬性,查找後發現是TQRichTextBaseRun的屬性,注釋說是是否響應觸摸
                      5. 如果響應觸摸
                        1. 在richTextRunRectDic中添加鍵值對,key為rect,value為run。
                        2. 設置循環的條件,釋放CF類型的變量。CF類型的變量不支持ARC。
                        3. 繼續尋找TQRichTextView中重載系統的方法。返現touchesBegan和touchesEnd方法。閱讀這兩個方法。
                          1. 拿到觸摸的點,轉換點的坐標為以左下角為原點是的坐標。
                          2. 判斷是否能只想delegate
                          3. 遍歷richTextRunRectDic,判斷點是否在rect中。如果在則調用delegate方法。
                          4. 主要功能分析完畢。
                          5. 通讀TQRichTextBaseRun,了解其它屬性和一些屬性的默認值。
                          6. 至此,整個TQRichTextViewDemo基本分析完畢。可得出如下結論。
                            1. 類的結構關系
                              1. TQRichTextEmojiRun—> TQRichTextImageRun—> TQRichTextBaseRun。
                              2. TQRichTextURLRun—> TQRichTextBaseRun。
                              3. TQRichTextEmojiRun和TQRichTextURLRun分別實現了analyzeText:runsArray方法用來從字符串中取出所需要的文字,並創建TQRichTextBaseRun對象添加進數組保存。
                              4. TQRichTextEmojiRun和TQRichTextURLRun分別重載了replaceTextWithAttributedString方法來在字符串的特定range處添加Attributed屬性。
                              5. TQRichTextEmojiRun和TQRichTextURLRun分別重載了drawRunWithRect方法實現了自定義位置,並返回是否繪制了內容。
                              6. 流程
                                1. 給TQRichTextView更改屬性。
                                2. 調用drawRect。
                                3. 調用TQRichTextEmojiRun和TQRichTextURLRun的analyzeText:runsArray方法解析字符串。
                                4. 創建NSAttributedString。
                                5. 為NSAttributedString添加屬性。
                                6. 調用TQRichTextEmojiRun和TQRichTextURLRun的replaceTextWithAttributedString方法為字符串添加屬性。
                                7. CoreText繪制NSAttributedString。
                                8. 調用TQRichTextEmojiRun和TQRichTextURLRun的drawRunWithRect方法實現自定義繪制。
                                9. 保存run和rect進字典,從字典取值判斷是否能點擊。
                                10. 有以上可以得出結論,若要更換表情和文字的解析規則,則只需去TQRichTextEmojiRun或TQRichTextURLRun修改analyzeText:runsArray,replaceTextWithAttributedString,drawRunWithRect三個方法。
                                  1. analyzeText:runsArray修改解析規則。
                                  2. replaceTextWithAttributedString修改添加屬性。
                                  3. drawRunWithRect修改自定義繪制。
                                  4. 若要實現點擊,只需設置isResponseTouch為YES並實現TQRichTextViewDelegate。
                                  5. 由以上閱讀代碼發現如下缺陷
                                    1. TQRichTextView的awakeFromNib方法沒實現,如過使用xib拖拽,則無法為TQRichTextView添加默認屬性。
                                      1. 解決方法,添加awakeFromNib方法,並在其中為默認屬性賦值。
                                      2. sizeWithFont和boundingRectWithSize:options:attributes:context:方法計算時不會計算行間距,TQRichTextView的lineSpacing若不設置為0會導致兩方法計算的高度比TQRichTextView實際顯示需要的高度小。
                                        1. 解決方法,TQRichTextView的lineSpacing設置為0。
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved