字符串转富文本
最近项目遇到的问题,因为后台返回的数据是HTML字符串,所以就按照常规处理方式把HTML字符串转换成富文本的字符串来处理,事实证明,tableview会非常卡,并且造成线程阻塞,无法响应事件
解决方案1.首先我想到的是把耗时操作放在子线程来操作
解决方案2. 因为是cell展示,所以只需要展示文本信息就行,那就过滤掉HTML标签,瞬间解决所有问题。所以在列表展示数据的时候HTML转换NSAttributedString一定要慎用
下面简单介绍一下NSScanner
NSScanner是一个类,用于在字符串中扫描指定的字符,翻译成我们需要的字符串或者数字,核心就是位置的移动 即scanLocation的移动变化
在上面的方法中首先指明了要扫描的对象 html(NSString) NSString * text 很重要 把我们要扫描出来的字符串存到text里面
而这个扫描到的字符串就是>之前的字符串 scanUpToString这个方法的意思是将scanLocation停留在>之前 并把之前的字符串传给text。
回头来看看我们去除html标签的方法 整个过程都是在扫描过程中进行的NSScanner在执行scanUpToString这个方法时一旦扫描到需要的字符串比如例子中的“<”,其scanLocation就会变为html的初始位置。所以,要在执行完一次完整的扫描后 把html标签用空字符串替换掉,在进行下一次扫描,也就是说再while中 html字符串的标签字符会越来越少,而每次扫描的初始位置相对没有变化都停留在上一次扫描结束的位置,即"<"标签的前面。
参考链接----传送门
笔者性懒,腹中无墨app嵌html屡见不鲜, 本文描述加载简单的html网页。
首先说明需求: 有网的状态直接从获取html网页并且缓存, 无网状态先从缓存读取html, 若不成功则加载本地html文件, 并且将本地html文件写入缓存, 以便下次读取.
1.加载html网页, viewWillAppear或者viewDidLoad.
以下QAUrl均为html完整的url
2.若成功, 就在成功的代理方法里, 将网页端html写入缓存
3.不成功,在失败的代理方法里, 加载磁盘缓存或者本地html,其中isNetConnected是指是否连接到互联网, 默认是true,加载失败后置为false.
fileprivate var isNetConnected: Bool = true // 是否连接到互联网
4.同样,此次成功后,在代理方法里,将本地html文件写入缓存
5.代理方法的里很简洁
6.需要注意的是
(1)拼接缓存地址时, 如果html的URL类似于" http://10.0.4.2:82/app/qa.html ",不能作为地址拼接,否则无法缓存.
(2)笔者将拼接地址统一写成"/Caches/feedback.html",若有新的缓存,则地址被覆盖,不会导致缓存多个相同文件,一般无需清理或者导致内存警告
(3)本文不涉及缓存图片, js交互等问题
7.补充:
开发过程中,笔者又遇到了一个问题,有网的情况下,网页也可能出现加载不成功.这个时候如果只是加载网页就会什么都没有.所以在viewWillAppear或者viewDidLoad里应该有个判断
如果请求request返回的finish是true即成功,则加载html网页,不成功则加载缓存.
前几天在进行项目的迭代开发时收到QA的一个测试bug,说是在APP使用过程中出现卡顿,经过排查,终于发现了罪魁祸首NSAttributedString NSHTMLTextDocumentType。
当你看到这篇文章时,很可能你也遇到了NSAttributedString的initWithData:options:documentAttributes:error:接口初始化HTML字符串的问题,这个接口的已知问题有:耗时较长,偶现crash,在不同版本系统上的表现不一致等。
经本人亲自测试,initWithData接口最大的问题就是初始化HTML字符串时耗时很大。我用的是iPhone 8Plus手机,处理一段HTML文本时耗时惊人(HTML比较复杂,包含图片),并且在某些iOS系统上,偶现超时的问题,导致UI卡死。
为防止阻塞主线程,可以尝试切换到非主线程执行:
附:查阅相关资料,目前还没有更好的解决方法。如有更好的解决方法,欢迎留言告知。