class CustomTextView: UITextView, NSTextLayoutManagerDelegate {
var padding: CGFloat
// Custom Initializer
init(frame: CGRect, textContainer: NSTextContainer?, padding: CGFloat) {
self.padding = padding
super.init(frame: frame, textContainer: textContainer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - NSTextLayoutManagerDelegate
func textLayoutManager(_ textLayoutManager: NSTextLayoutManager,
textLayoutFragmentFor location: NSTextLocation,
in textElement: NSTextElement) -> NSTextLayoutFragment {
let index = textLayoutManager.offset(from: textLayoutManager.documentRange.location, to: location)
// Make sure the string is not empty
if textStorage.length > 0 {
let attributedString = textStorage.attributedSubstring(from: NSRange(location: index, length: 1))
// Check for an NSTextAttachment at the first position
if let attachment = attributedString.attribute(.attachment, at: 0, effectiveRange: nil) as? NSTextAttachment, attachment.image != nil {
// The first character is an image
// Return the default NSTextLayoutFragment
return NSTextLayoutFragment(textElement: textElement, range: textElement.elementRange)
}
}
// Otherwise, return a custom NSTextLayoutFragment with padding
return TextLayoutFragment(textElement: textElement, range: textElement.elementRange, padding: padding)
}
}
class TextLayoutFragment: NSTextLayoutFragment {
var padding: CGFloat
// custom initializer
init(textElement: NSTextElement, range: NSTextRange?, padding: CGFloat) {
self.padding = padding
super.init(textElement: textElement, range: range)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var leadingPadding: CGFloat { return padding }
override var trailingPadding: CGFloat { return padding }
}