专业java、php、iOS、C++、网页设计、平面设计、网络营销、游戏开发、前端与移动开发培训机构
正则表达式
从复杂的文本中按一定的规则找出需要的内容.正则表达式就是描述这个规则语句.
- 有关正则表达式的参考文档链接:http://deerchao.net/tutorials/regex/regex.htm
目标:从服务器返回的
来源中提取需要的字符串
- 匹配方案 (pattern)
.匹配任意字符(除换行符)*匹配 0~任意 多个字符?尽可能少的重复
- 匹配函数 (NSRegularExpression)
matchesInString- 重复匹配多次
pattern - 如果匹配成功,生成
NSTextCheckingResult数组
- 重复匹配多次
firstMatchInString- 匹配第一个
pattern - 如果匹配成功,生成
NSTextCheckingResult
- 匹配第一个
- 正则表达式常用选项 (NSRegularExpressionOptions)
CaseInsensitive忽略大小写DotMatchesLineSeparators.匹配换行符
- 匹配结果 (NSTextCheckingResult)
numberOfRanges- 匹配的
range计数
- 匹配的
rangeAtIndex- 第
index个匹配项的范围
- 第
- 可以利用
NSString的substringWithRange取得匹配结果
表情字符串转表情
- 微博中的表情字符串转换成表情图片
- 1.获取微博文本中的表情字符串
- 2.根据表情字符串获取表情模型
- 3.根据表情模型创建带表情图片的属性文本
- 4.将文本中的表情字符串替换成带表情图片的属性文本
- 新建项目
- 将
HMEmoticonKeyboard(表情键盘)目录拖拽到新建项目中,注意不要勾选Copy items if needed,如下图所示
这样做的好处是,开发测试时,一旦对代码进行调整,原始项目中的代码会一起调整
- 设定目标
- 给定一个表情字符串文字
我[爱你]啊[笑哈哈]!返回对应的属性文本 [爱你]来自默认分组[笑哈哈]来自浪小花分组
- 给定一个表情字符串文字
先做第3步
根据表情模型创建带表情图片的属性文本- 注释
UITextView+Emoticon.swift中insertEmoticon方法中的 创建附件添加到属性文本的代码// // 附件,图片可以作为附件,附件可以添加到属性文本 // let attachment = HMTextAttachment() // attachment.image = UIImage(contentsOfFile: pngPath) // attachment.chs = emoticon.chs // // // 获取文本的高度 // let height = font?.lineHeight ?? 10 // // 设置附件的大小 // attachment.bounds = CGRect(x: 0, y: -4, width: height, height: height) // // // 创建带附件的属性文本,并且添加font属性 // let attrString = NSMutableAttributedString(attributedString: NSAttributedString(attachment: attachment)) // attrString.addAttribute(NSFontAttributeName, value: font!, range: NSRange(location: 0, length: 1)) 在
HMEmoticonModel.swift添加toAttrString方法/// 将emoticon表情模型转成带图片附件的属性文本 func toAttrString(font: UIFont) -> NSAttributedString { // 附件,图片可以作为附件,附件可以添加到属性文本 let attachment = HMTextAttachment() attachment.image = UIImage(contentsOfFile: fullPngPath!) attachment.chs = chs // 获取文本的高度 let height = font.lineHeight // 设置附件的大小 attachment.bounds = CGRect(x: 0, y: -4, width: height, height: height) // 创建带附件的属性文本,并且添加font属性 let attrString = NSMutableAttributedString(attributedString: NSAttributedString(attachment: attachment)) attrString.addAttribute(NSFontAttributeName, value: font, range: NSRange(location: 0, length: 1)) return attrString }
- 注释
根据
字符串找到对应的表情模型override func viewDidLoad() { super.viewDidLoad() let text = "我[爱你]啊[笑哈哈]!" let model = emoticonMode(withEmoticonName: "[爱你]") print("model = \(model)") }/** 根据表情名称查找表情模型 - parameter name: 表情名称 - returns: 表情模型 */ private func emoticonMode(withEmoticonName name: String) -> HMEmoticonModel? { // 去所有的表情包里面找 for package in HMEmoticonManager.shared.packages { for emoticon in package.emoticons { if emoticon.chs == name { // 找到了 return emoticon } } } return nil }抽取
emoticonMode(withEmoticonName name: String)到HMEmoticonModel模型中/** 根据表情名称查找表情模型 - parameter name: 表情名称 - returns: 表情模型 */ class func emoticonMode(withEmoticonName name: String) -> HMEmoticonModel? { // 去所有的表情包里面找 for package in HMEmoticonManager.shared.packages { for emoticon in package.emoticons { if emoticon.chs == name { // 找到了 return emoticon } } } return nil }使用正则表达式过滤表情字符串
class ViewController: UIViewController { @IBOutlet weak var textView: UITextView! /* 1.获取微博文本中的表情字符串 2.根据表情字符串获取表情模型 3.根据表情模型创建带表情图片的属性文本 4.将文本中的表情字符串替换成带表情图片的属性文本 */ override func viewDidLoad() { super.viewDidLoad() let text = "我[爱你]啊[笑哈哈]!" // let model = HMEmoticonModel.emoticonMode(withEmoticonName: "[爱你]") // print("model = \(model)") textView.attributedText = emoticonAttrText(withString: text) }func emoticonAttrText(withString string: String) -> NSAttributedString { // 获取文本中的表情字符串 // 定义匹配方案 let pattern = "\\[.*?\\]" // 创建正则表达式对象 let regular = try! NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.dotMatchesLineSeparators) // 匹配所有符合条件的内容 let result = regular.matches(in: string, options: [], range: NSRange(location: 0, length: string.characters.count)) // 定义属性字符串 let emoticonString = NSMutableAttributedString(string: string) // 从后面往前面遍历 for result in result.reversed() { // 获取匹配结果的第一个匹配项 let range = result.rangeAt(0) // 截取表情字符串 let emoticonStr = (string as NSString).substring(with: range) // 表情名称转表情模型 if let emoticon = HMEmoticonModel.emoticonMode(withEmoticonName: emoticonStr) { // 表情模型转带表情图片的属性文本 let emoticonAttr = emoticon.toAttrString(font: UIFont.systemFont(ofSize: 15)) // 表情字符串替换为带表情图片的属性文本 emoticonString.replaceCharacters(in: range, with: emoticonAttr) } } return emoticonString } }抽取
emoticonAttrText(withString string: String)到HMEmoticonManager类中
在微博项目中使用表情文字
- 重新打开微博项目,会发现测试好的函数已经在那里
修改
HMStatusViewModel, 添加原创微博带表情的文本originalAttrText,被转发微博带表情的文本retweetAttrText, 在init构造函数中设置init(status: HMStatus) { self.status = status super.init() ... originalAttrText = HMEmoticonManager.shared.emoticonAttrText(withString: status.text ?? "") retweetAttrText = HMEmoticonManager.shared.emoticonAttrText(withString: retweetStatusText ?? "") calcRowHeight() }在计算配图高度时使用
originalAttrText和retweetAttrText设置高度// 原创微博文字高度 if let originalAttrText = originalAttrText { // 根据给定的Size真正计算文字的宽高 rowHeight += originalAttrText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil).height }if isRetweetedStatus { // 转发微博 rowHeight += HMStatusCellMargin // 注意: 被转发微博内容 @用户名称: 微博内容 if let retweetAttrText = retweetAttrText { rowHeight += retweetAttrText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil).height rowHeight += calcSize(count: retweetStatusPictureURLs?.count ?? 0).height } }在
Cell中设置内容时,使用属性文本statusText.attributedText = statusVM?.originalAttrText// 判断是原创微博还是转发微博 if statusVM!.isRetweetedStatus { // 转发微博 pictureView.imageURLs = statusVM?.retweetStatusPictureURLs // 被转发微博内容 retweetStatusText.attributedText = statusVM?.retweetAttrText }