diff --git a/CHANGELOG.md b/CHANGELOG.md index ada09751..2373e7a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -335,6 +335,11 @@ Version 4.0.0 comes with couple of breaking changes, please refer to [MIGRATION_ ## [2.0.0-beta.1](https://github.com/MessageKit/MessageKit/releases/tag/2.0.0-beta.1) +### Fixed + +- Fixed `boundingRect(with:options:)` miscalculation of `MessageLabel` by using `NSLayoutManager`, like text `Ꮚ˘̴͈́ꈊ˘̴͈̀Ꮚ⋆✩`、`Tomorrow is the day`. +[#824](https://github.com/MessageKit/MessageKit/pull/824) by [@zhongwuzw](https://github.com/zhongwuzw). + ### Changed - **Breaking Change** Updated codebase to Swift 4.2 [#883](https://github.com/MessageKit/MessageKit/pull/883) by [@nathantannar4](https://github.com/nathantannar4) diff --git a/Sources/Layout/MessageSizeCalculator.swift b/Sources/Layout/MessageSizeCalculator.swift index 1d9065c9..09948721 100644 --- a/Sources/Layout/MessageSizeCalculator.swift +++ b/Sources/Layout/MessageSizeCalculator.swift @@ -316,15 +316,33 @@ open class MessageSizeCalculator: CellSizeCalculator { } // MARK: Internal + internal lazy var textContainer: NSTextContainer = { + let textContainer = NSTextContainer() + textContainer.maximumNumberOfLines = 0 + textContainer.lineFragmentPadding = 0 + return textContainer + }() + internal lazy var layoutManager: NSLayoutManager = { + let layoutManager = NSLayoutManager() + layoutManager.addTextContainer(textContainer) + return layoutManager + }() + internal lazy var textStorage: NSTextStorage = { + let textStorage = NSTextStorage() + textStorage.addLayoutManager(layoutManager) + return textStorage + }() internal func labelSize(for attributedText: NSAttributedString, considering maxWidth: CGFloat) -> CGSize { let constraintBox = CGSize(width: maxWidth, height: .greatestFiniteMagnitude) - let rect = attributedText.boundingRect( - with: constraintBox, - options: [.usesLineFragmentOrigin, .usesFontLeading], - context: nil).integral - return rect.size + textContainer.size = constraintBox + textStorage.replaceCharacters(in: NSRange(location: 0, length: textStorage.length), with: attributedText) + layoutManager.ensureLayout(for: textContainer) + + let size = layoutManager.usedRect(for: textContainer).size + + return CGSize(width: size.width.rounded(.up), height: size.height.rounded(.up)) } } diff --git a/Sources/Views/MessageLabel.swift b/Sources/Views/MessageLabel.swift index feb9c95a..91f388a8 100644 --- a/Sources/Views/MessageLabel.swift +++ b/Sources/Views/MessageLabel.swift @@ -130,7 +130,7 @@ open class MessageLabel: UILabel { open override func drawText(in rect: CGRect) { let insetRect = rect.inset(by: textInsets) - textContainer.size = CGSize(width: insetRect.width, height: rect.height) + textContainer.size = CGSize(width: insetRect.width, height: insetRect.height) let origin = insetRect.origin let range = layoutManager.glyphRange(for: textContainer)