专业java、php、iOS、C++、网页设计、平面设计、网络营销、游戏开发、前端与移动开发培训机构

正则表达式

从复杂的文本中按一定的规则找出需要的内容.正则表达式就是描述这个规则语句.

目标:从服务器返回的 来源 中提取需要的字符串

  • 匹配方案 (pattern)
    • . 匹配任意字符(除换行符)
    • * 匹配 0~任意 多个字符
    • ? 尽可能少的重复
  • 匹配函数 (NSRegularExpression)
    • matchesInString
      • 重复匹配多次 pattern
      • 如果匹配成功,生成 NSTextCheckingResult 数组
    • firstMatchInString
      • 匹配第一个 pattern
      • 如果匹配成功,生成 NSTextCheckingResult
  • 正则表达式常用选项 (NSRegularExpressionOptions)
    • CaseInsensitive 忽略大小写
    • DotMatchesLineSeparators . 匹配换行符
  • 匹配结果 (NSTextCheckingResult)
    • numberOfRanges
      • 匹配的 range 计数
    • rangeAtIndex
      • index 个匹配项的范围
    • 可以利用 NSStringsubstringWithRange 取得匹配结果

表情字符串转表情

  • 微博中的表情字符串转换成表情图片
    • 1.获取微博文本中的表情字符串
    • 2.根据表情字符串获取表情模型
    • 3.根据表情模型创建带表情图片的属性文本
    • 4.将文本中的表情字符串替换成带表情图片的属性文本
  • 新建项目
  • HMEmoticonKeyboard(表情键盘) 目录拖拽到新建项目中,注意不要勾选 Copy items if needed,如下图所示

    这样做的好处是,开发测试时,一旦对代码进行调整,原始项目中的代码会一起调整


  1. 设定目标
    • 给定一个表情字符串文字 我[爱你]啊[笑哈哈]! 返回对应的属性文本
    • [爱你] 来自 默认 分组
    • [笑哈哈] 来自 浪小花 分组
  2. 先做第3步 根据表情模型创建带表情图片的属性文本

    • 注释 UITextView+Emoticon.swiftinsertEmoticon 方法中的 创建附件添加到属性文本的代码
      //            // 附件,图片可以作为附件,附件可以添加到属性文本
      //            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
      }
      
  3. 根据 字符串 找到对应的 表情模型

    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
    }
    
  4. 抽取 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
    }
    
  5. 使用正则表达式过滤表情字符串

    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
      }
    }
    
  6. 抽取 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()
    }
    
  • 在计算配图高度时使用 originalAttrTextretweetAttrText 设置高度

    // 原创微博文字高度
    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
    }
    

results matching ""

    No results matching ""