iOS提取文本中链接添加高亮点击,String NSString 对于表情NSRange计算长度不同,YYTextHighlight手势冲突问题

直接上代码,通过以下计算就可以完成链接的识别以及替换,然后添加高亮以及对高亮文字添加点击事件

let label = YYLabel()
        label.backgroundColor = .red
        label.numberOfLines = 0
        label.preferredMaxLayoutWidth = 200
        view.addSubview(label)
        label.snp.makeConstraints { (make) in
            make.left.equalTo(50)
            make.width.equalTo(200)
            make.top.equalTo(300)
        }
        
        var urls: [String] = []
        
        var string = "test\\n\ntest/\\n\n😂\nhttps://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_9827769369551786176%22%7D&n_type=0&p_from=1 第二个 https://weibo.com/mygroups?gid=201209041125312675&wvr=6&leftnav=1&isspecialgroup=1 今天又是好天气!今天又是好天气!今天又是好天气!今天又是好天气!今天又是好天气!";
        
//        var string = "est\\n\ntest/\\n\n😂\nhttps://www.weibo.com/beat/beatslist/beat?keyword=测试 https://weibo.com/mygroups?gid=201209041125312675&wvr=6&leftnav=1&isspecialgroup=1 每天都很美好";

        let detector = try? NSDataDetector.init(types: NSTextCheckingResult.CheckingType.link.rawValue)
        let matches = detector?.matches(in: string, options: [.reportProgress], range: NSRange(location: 0, length: string.count))
        for match in matches! {
            if match.resultType == .link {
                if let url = match.url {
                    //这里获取到的url是经过encode处理的
                    urls.append(url.absoluteString)
                }
            }
        }
        
        print("encode urls \(urls)")
        
        let font = UIFont.systemFont(ofSize: 15)
        let attribbutes = NSMutableAttributedString(string: "")
        for str in urls {
           
            var strArray = string.components(separatedBy: str)
            if strArray.count < 2 {
                //如果没有匹配到字符说明string没有经过encode,但是str为encode以后的字符,所以需要decode str才能识别
                if let decode = str.removingPercentEncoding {
                    strArray = string.components(separatedBy: decode)
                }
            }
            if let firstStr = strArray.first {
                let subAttribute = NSMutableAttributedString(string: firstStr)
                subAttribute.setColor(.cyan, range: NSRange(location: 0, length: firstStr.count))
                attribbutes.append(subAttribute)
                
                let hightText = YYTextHighlight()
                hightText.tapAction = { view, text, range, rect in
                    guard let url = URL(string: str) else {
                        print("error url \(str)")
                        return
                    }
                    print("open url \(url)")
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                }
                
                let imageAttribute = NSMutableAttributedString.attachmentString(withContent: UIImage(named: "commend_kink"), contentMode: .scaleAspectFit, attachmentSize: .init(width: 18, height: 18), alignTo: font, alignment: .center)
                let replaceStr = NSMutableAttributedString(string: "查看链接")
                replaceStr.setColor(.yellow, range: NSRange(location: 0, length: 4))
                imageAttribute.append(replaceStr)
                imageAttribute.setTextHighlight(hightText, range: NSRange(location: 0, length: 5))
                attribbutes.append(imageAttribute)
            }
            
            if let lastStr = strArray.last {
                string = lastStr
            }
            
        }
        let lastAttribute = NSMutableAttributedString(string: string)
        lastAttribute.setColor(.cyan, range: NSRange(location: 0, length: string.count))
        attribbutes.append(lastAttribute)
        
        label.attributedText = attribbutes
注意点YYLabel UILabel用法差异

使用YYLabel和使用UILabel还是有一些区别的。如果使用UILabel设置了lable的font、textColor,在给label的text赋值或者attributedText赋值时,上述设置都会生效。但是YYLabel设置font、textColor只会对label的text生效,对于attributedText属性必须对NSAttributedString、NSMutableAttributedString进行设置。

YYLabel高度自适应 preferredMaxLayoutWidth

对于UIlabel仅设置label.numberOfLines = 0,并且不设置高度lable就会随着显示内容自动增长,但是对于YYLable除了设置label.numberOfLines = 0,还要设置label.preferredMaxLayoutWidth,只有这样YYLabel才会自增长。

String NSString 对于表情NSRange计算长度不同

由下图可以看出对于纯文字不管是String类型NSString计算结果都一样。但是对于含有表情的文本计算,两者计算结果不一样。对于这种情况可以使用NSString计算也可以使用String调用.utf16.coun计算。NSString默认使用utf16计算,而表情大部分也需要使用utf16计算,所以直接使用NSString就可以得到正确的结果。

 let range = NSMakeRange(0, string.count)
 let nsStr = string as NSString
 let conTentRange = NSMakeRange(0, nsStr.length)
 //let conTentRange = NSMakeRange(0, string.utf16.count)
 printf("range \(range) conTentRange \(conTentRange)  text \(text)")
image
YYTextHighlight和父视图手势会冲突问题
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        //YYTextHighlight和父视图手势会冲突,所以需要识别点击位置是否包含YYTextHighlight
        if touch.view is YYLabel {
            let label = touch.view as? YYLabel
            if let label = label {
                var range = NSMakeRange(0, 1);
                let highlight = label._getHighlight(at: touch.location(in: label), range: &range)
                if highlight != nil {
                    return false
                }
            }
        }
        return true
    }

上边代码中-(YYTextHighlight *)_getHighlightAtPoint:(CGPoint)point range:(NSRangePointer)range;为私有方法,外部不可调用,又考虑到引用的是别人的第三方库,所以需要创建一个YYLabel的分来,然后将此方法在YYLabel分类的.h中声明。如下:

#import "YYLabel.h"

NS_ASSUME_NONNULL_BEGIN

@interface YYLabel (YHYYLabel)

- (YYTextHighlight *)_getHighlightAtPoint:(CGPoint)point range:(NSRangePointer)range;

@end

NS_ASSUME_NONNULL_END

本人原文博客地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 为什么要做这个笔记 masonry [https://github.com/SnapKit/Masonry]可以说...
    blackie_james阅读 681评论 0 0
  • 利用NSAttributedString (富文本)能调整UILable等文字相关控件显示文字的字体、颜色、字体间...
    Sweet丶阅读 2,324评论 0 0
  • Auto Layout 是怎么进行自动布局的,性能如何? Auto Layout 到底是如何实现自动布局的,这种布...
    为了自由的白菜阅读 267评论 0 0
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,032评论 0 4
  • 公元:2019年11月28日19时42分农历:二零一九年 十一月 初三日 戌时干支:己亥乙亥己巳甲戌当月节气:立冬...
    石放阅读 6,870评论 0 2