iOS开发--从TQRichTextViewDemo中学会分析project
下载地址:
http://code4app.com/ios/TQRichTextView/5244fe9c6803fa0862000000
1.首先找到AppDelegate类。不管一个project有多么复杂,多么多的类。但入口仅仅有一个就是AppDelegate类的didFinishLaunchingWithOptions方法。我们阅读别人源码的时候能够从这里入手。
在TQRichTextViewDemoproject中。这种方法中仅创建了一个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方法。
- 在drawRect中首先调用了analyzeText方法,传入了參数_text。并把返回值赋给了_textAnalyzed。
- 去看analyzeText方法。
首先清空了数组和字典。然后定义了一个NSString类型的result变量和NSMutableArray类型的array并赋值为richTextRunsArray。
- 运行TQRichTextEmojiRun的一个方法。传入string和array的指针。
- 由于这种方法是TQRichTextEmojiRun的类方法。全部我们直接去看该方法,而不用去看TQRichTextEmojiRun的初始化方法。连蒙带猜的我们能够确定这种方法应该是解析字符串中表情的方法。看重点。发现假设解析到表情。那么就创建一个TQRichTextEmojiRun的队形,range=表情字符串在string中的range,originalText=表情字符串,把这个创建的对象放入传进来的数组指针中。最后替换传入字符串中的表情字符串为空格,并返回被替换过表情的字符串。
- 通过看TQRichTextEmojiRun的init方法。发现初始化时设置了两个变量,来自父类TQRichTextBaseRun。分别设置了TQRichTextRunType和是否响应触摸。
发现TQRichTextURLRun也继承自TQRichTextBaseRun。
- 跳出这种方法,回到analyzeText中,继续往下看。
- 运行TQRichTextURLRun的一个方法,传入result和array的指针。
- 同上,直接去看这种方法的实现。
从和TQRichTextEmojiRun的命名格式类似,调用的方法名类似,我们能够推測这种方法是解析URL的,那么就直接看重点。发现,假设找到匹配的字符串。就创建一个TQRichTextURLRun的对象,设置range=URL的range,originText = URL。然后把对象加入到传进来的数组中。最后返回string。
- 通过看TQRichTextURLRun的init方法,发现同上初始化时设置了两个变量。来自父类TQRichTextBaseRun,分别设置了TQRichTextRunType和是否响应触摸。发现TQRichTextEmojiRun继承自TQRichTextImageRun,TQRichTextImageRun继承自TQRichTextBaseRun。
- 跳出这种方法,回到analyzeText中,继续往下看。
- 同上,直接去看这种方法的实现。
- 遍历richTextRunsArray中的对象,每一个对象调用setOriginalFont方法,传入參数self.font。通过阅读上面的两个方法的内部实现明确richTextRunsArray中保存的是TQRichTextEmojiRun和TQRichTextURLRun对象,所以去看这两个对象的setOriginalFont方法。
- 这个设置的是继承自父类TQRichTextBaseRun的属性。
- 回到analyzeText继续往下看。
- 返回result,跳出这种方法。继续看drawRect。
- 去看analyzeText方法。
- 接下来是创建NSAttrbutedString。并赋值一些属性。
- 文本处理,遍历richTextRunsArray中的对象,每一个对象调用replaceTextWithAttributedString方法。
- 在TQRichTextEmojiRun没有找到replaceTextWithAttributedString方法。那就去TQRichTextImageRun中找。阅读该方法。
- 传入的attrString删除占位的空格字符。
- 创建CTRunDelegateCallbacks,返现设定的宽高为OriginalFont的高度的1.1倍。
- 创建空格NSAttrbutedString对象。加入CTRunDelegateRef属性。
- 把空格NSAttrbutedString对象插入至传入的attrString。
- 查看super方法,发如今这段range上还设置了一个键值对,key为TQRichTextAttribute,value为自己。
- 同上阅读TQRichTextURLRun的replaceTextWithAttributedString方法。
- 为该段range的文字加入蓝色字体。
- 调用super方法。为该段range加入同上的key-value键值对。
- 返回继续阅读drawRect。
- 在TQRichTextEmojiRun没有找到replaceTextWithAttributedString方法。那就去TQRichTextImageRun中找。阅读该方法。
- 以下是绘制的准备工作。不想研究咋绘制的粗读即可。
- 清空richTextRunRectDic
- 绘制,不想研究的也可粗读略过。
- 找重点。绘制替换过的特殊文本单元。
- 遍历取出每个run,取出run的attributes中key为TQRichTextAttribute的值。
- 假设值存在,则说明,这个run是特殊的run。
- 求run的frame,粗读略过。
- 调用drawRunWithRect方法,并将返回值赋给idDraw变量。
- TQRichTextEmojiRun的drawRunWithRect方法中绘制了表情图片,返回YES。
- TQRichTextURLRun的drawRunWithRect方法返回NO。
- TQRichTextBaseRun的drawRunWithRect方法返回NO。
- 推断run的isResponseTouch属性,查找后发现是TQRichTextBaseRun的属性,凝视说是是否响应触摸
- 假设响应触摸
- 在richTextRunRectDic中加入键值对,key为rect,value为run。
- 设置循环的条件。释放CF类型的变量。CF类型的变量不支持ARC。
- 在drawRect中首先调用了analyzeText方法,传入了參数_text。并把返回值赋给了_textAnalyzed。
- 继续寻找TQRichTextView中重载系统的方法。
返现touchesBegan和touchesEnd方法。阅读这两个方法。
- 拿到触摸的点,转换点的坐标为以左下角为原点是的坐标。
- 推断能否仅仅想delegate
- 遍历richTextRunRectDic。推断点是否在rect中。假设在则调用delegate方法。
- 主要功能分析完成。
- 通读TQRichTextBaseRun。了解其他属性和一些属性的默认值。
- 至此,整个TQRichTextViewDemo基本分析完成。可得出例如以下结论。
- 类的结构关系
- TQRichTextEmojiRun—> TQRichTextImageRun—> TQRichTextBaseRun。
- TQRichTextURLRun—> TQRichTextBaseRun。
- TQRichTextEmojiRun和TQRichTextURLRun分别实现了analyzeText:runsArray方法用来从字符串中取出所须要的文字。并创建TQRichTextBaseRun对象加入进数组保存。
- TQRichTextEmojiRun和TQRichTextURLRun分别重载了replaceTextWithAttributedString方法来在字符串的特定range处加入Attributed属性。
- TQRichTextEmojiRun和TQRichTextURLRun分别重载了drawRunWithRect方法实现了自己定义位置,并返回是否绘制了内容。
- 流程
- 给TQRichTextView更改属性。
- 调用drawRect。
- 调用TQRichTextEmojiRun和TQRichTextURLRun的analyzeText:runsArray方法解析字符串。
- 创建NSAttributedString。
- 为NSAttributedString加入属性。
- 调用TQRichTextEmojiRun和TQRichTextURLRun的replaceTextWithAttributedString方法为字符串加入属性。
- CoreText绘制NSAttributedString。
- 调用TQRichTextEmojiRun和TQRichTextURLRun的drawRunWithRect方法实现自己定义绘制。
- 保存run和rect进字典。从字典取值推断能否点击。
- 有以上能够得出结论,若要更换表情和文字的解析规则。则仅仅需去TQRichTextEmojiRun或TQRichTextURLRun改动analyzeText:runsArray,replaceTextWithAttributedString,drawRunWithRect三个方法。
- analyzeText:runsArray改动解析规则。
- replaceTextWithAttributedString改动加入属性。
- drawRunWithRect改动自己定义绘制。
- 若要实现点击,仅仅需设置isResponseTouch为YES并实现TQRichTextViewDelegate。
- 类的结构关系
- 由以上阅读代码发现例如以下缺陷
- TQRichTextView的awakeFromNib方法没实现。如过使用xib拖拽,则无法为TQRichTextView加入默认属性。
- 解决方法。加入awakeFromNib方法。并在当中为默认属性赋值。
- sizeWithFont和boundingRectWithSize:options:attributes:context:方法计算时不会计算行间距,TQRichTextView的lineSpacing若不设置为0会导致双方法计算的高度比TQRichTextView实际显示须要的高度小。
- 解决方法。TQRichTextView的lineSpacing设置为0。
- TQRichTextView的awakeFromNib方法没实现。如过使用xib拖拽,则无法为TQRichTextView加入默认属性。
iOS开发--从TQRichTextViewDemo中学会分析project的更多相关文章
- iOS开发——C篇&动态内存分析
再C语言中关于内存是一个很重要的知识点,所以今天我就从c语言的内存分配开始为大家解析一下C语言再iOS开发中非常重要的一些知识. 1:malloc函数的介绍 C语言中开辟内存空间:malloc函数(堆 ...
- iOS开发之动画中的时间(概况)
一.引言 在iOS开发中使用动画时,可以通过设置动画的duration.speed.begintime.offset属性,来设置动画的时长.速度.起始时间及起始偏移. 用一个简单的例子来说明各个参数的 ...
- (转)iOS 开发,工程中混合使用 ARC 和非ARC
[前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...
- iOS 开发,工程中混合使用 ARC 和非ARC(转)
[前提知识] ARC:Automatic Reference Counting,自动引用计数 在开发 iOS 3 以及之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain. ...
- ios开发系列之内存泄漏分析(下)
接上篇,本篇主要讲解通知和 KVO 不移除观察者.block 循环引用 .NSThread 和 RunLoop一起使用造成的内存泄漏. 1.通知造成的内存泄漏 1.1.ios9 以后,一般的通知,都不 ...
- ios开发系列之内存泄漏分析(上)
ios自从引入ARC机制后,一般的内存管理就可以不用我们码农来负责了,但是一些操作如果不注意,还是会引起内存泄漏. 本文主要介绍一下内存泄漏的原理.常规的检测方法以及出现的常用场景和修改方法. 1. ...
- iOS开发关于xcode中souceControl的苹果文档翻译(节选)
Subversion 1.7 provides many benefits: svn1.7版本有以下好处: Improved performance. Increased speed for many ...
- iOS开发-修改UITableViewCell中image和title的位置和大小
最近在开发中遇到需要Cell中imageView和textLable位置和大小的情况,设计希望得到的结果如下图所示: 而TableViewCell默认样式,image是靠紧左边的,并且image和ti ...
- iOS HmacSHA1加密 和 MD5 Base64加密 --iOS开发系列---项目中成长的知识五
项目中开发中需要对一些数据进行加密后和服务器验证是否是我们客户端发出的请求! 方案是服务器定的,使用HmacSHA1加密和MD5 Base64加密 加密过程比较复杂 1.获取格林威治时间 2.用bas ...
随机推荐
- python - 接口自动化测试 - TestRegister - 注册接口测试用例
# -*- coding:utf-8 -*- ''' @project: ApiAutoTest @author: Jimmy @file: test_register.py @ide: PyChar ...
- 从输入url开始,完善前端体系架构
原文链接: https://segmentfault.com/a/1190000013662126 从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系! javascript 前端 23 ...
- Solr配置Ikanalyzer分词器
上一篇文章讲解在win系统中如何安装solr并创建一个名为test_core的Core,接下为text_core配置Ikanalyzer 分词器 1.打开text_core的instanceDir目录 ...
- PYTHON资源入口汇总
Python资源入口汇总 官网 官方文档 教程和书籍 框架 数据库 模板 工具及第三方包 视频 书籍 博客 经典博文集合 社区 其他 整理中,进度30% 官网 入口 官方文档 英文 document ...
- POJ 3481 Double Queue(Treap模板题)
Double Queue Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15786 Accepted: 6998 Des ...
- 优化Angularjs的$watch方法
Angularjs的$watch相信大家都知道,而且也经常使用,甚至,你还在为它的某些行为感到恼火.比如,一进入页面,它就会调用一次,我明明希望它在我初始化之后,值再次变动才调用.这种行为给我们带来许 ...
- css选择器位置和数量技巧
1. 除去首个元素 li:not(:first-child) li + li li:first-child ~ li 2. 第1-3个元素 li:nth-child(-n+3) 3. 除去第1-3个元 ...
- HTML+CSS 滚动条样式自定义 - 适用于 div,iframe, html 等
友言:这两天被滚动条整的无与伦比,在此做下总结: 首先自定义浏览器滚动条的实现原理:计算浏览器滚动条的高度,层级1的高度与滚动条的总高度是一样的,通过相似比例计算: 浏览器滚动条总高度 :滚动条高度 ...
- Replacing Accented characters(Diacritic) .NET
原文发布时间为:2012-02-17 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Collections.Generic;using Syste ...
- Use ASP.NET and DotNetZip to Create and Extract ZIP Files
原文发布时间为:2011-02-16 -- 来源于本人的百度文章 [由搬家工具导入] Published: 11 Feb 2011By: Scott MitchellDownload Sample C ...