1.创建CTRunDelegate
-
创建CTRunDelegate对象,并且传递callback和参数
var imageName = "e_banner" var imageCallBack = CTRunDelegateCallbacks(version: kCTRunDelegateVersion1, dealloc: { (_) in print("-------") }, getAscent: { (ascent) -> CGFloat in return 80 }, getDescent: { (descent) -> CGFloat in return 0 }) { (width) -> CGFloat in return 200 } let runDelegate = CTRunDelegateCreate(&imageCallBack, &imageName)
-
创建一个富文本类型的图片占位图,绑定代理
let imageString = NSMutableAttributedString(string: " ") imageString.addAttribute(NSAttributedString.Key(rawValue: kCTRunDelegateAttributeName as String), value: runDelegate!, range: NSRange(location: 0, length: 1)) imageString.addAttribute(NSAttributedString.Key.init(rawValue: "imageName"), value: imageName, range: NSRange(location: 0, length: 1))
-
将图片占位符插入到我们的富文本中
attString.insert(imageString, at: 14)
2.通过遍历CTLine中的CTRun计算图片所在位置
-
首先遍历CTLine
-
遍历每个Line下的CTRun
-
拿到每个CTRun的attribute属性,并判断代理是否为空,文字的代理为空,而图片代理是不为空的;
-
计算CTRun的frame
-
通过CTLine获取对应的原点,CTRunGetTypographicBounds获取宽和ascent,descent;
// 处理绘制图片的逻辑 let lines = CTFrameGetLines(frame) as Array var originsArrays = [CGPoint](repeating: CGPoint.zero, count: lines.count) let range = CFRangeMake(0, 0) CTFrameGetLineOrigins(frame, range, &originsArrays) for i in 0..<lines.count { let line = lines[i] let runs = CTLineGetGlyphRuns(line as! CTLine) as Array for j in 0..<runs.count { let run = runs[j] let attributes = CTRunGetAttributes(run as! CTRun) as NSDictionary if attributes.value(forKey: kCTRunDelegateAttributeName as String) == nil { continue } if let imageUrlStr = attributes["imageName"] as? String, let image = UIImage(named: imageUrlStr) { var runAscent = CGFloat() var runDescent = CGFloat() let lineOrigin = originsArrays[i] let width = CTRunGetTypographicBounds(run as! CTRun, CFRangeMake(0, 0), &runAscent, &runDescent, nil) let runRect = CGRect(x: lineOrigin.x + CTLineGetOffsetForStringIndex(line as! CTLine, CTRunGetStringRange(run as! CTRun).location, nil), y: lineOrigin.y - runDescent, width: CGFloat(width), height: runAscent + runDescent) imageFrame = runRect context?.draw(image.cgImage!, in: runRect) } } }
网友评论