给NextGrowingTextView添加扩展,支持设置光标大小。
NextGrowingTextView是一个第三方库,内部有一个继承自UITextView的NextGrowingInternalTextView,这个textview外部是访问不了的。而设置textview的光标大小需要继承UITextView并重写UITextInput.caretRect(for:)方法。怎么办呢?
大概有三种办法:
1、私有化NextGrowingTextView。直接改NextGrowingInternalTextView类。这种最简单,但是以后就需要自己维护这个库了。
2、方法交换UITextView的caretRect(for:)实现。这种也比较简单,但是由于交换的是UITextView的实现,影响的范围比较大。
3、动态给NextGrowingInternalTextView添加caretRect(for:)实现。这个影响的范围只有NextGrowingInternalTextView,并且也不需要私有化NextGrowingTextView。个人觉得是最佳的解决办法了。这个方案的难点是添加自己的实现后怎么调用父类的实现。解决办法就是先获取父类的IMP,再添加自己的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| extension NextGrowingTextView { private struct AssociatedKeys { static var caretSize = "caretSize" } var caretSize: CGSize? { get { return objc_getAssociatedObject(self, &AssociatedKeys.caretSize) as? CGSize } set { objc_setAssociatedObject(self, &AssociatedKeys.caretSize, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) hookCaretRectMethodOnce() } } private func hookCaretRectMethodOnce() { DispatchQueue.once { let cls: AnyClass = type(of: self.textView) let sel: Selector = #selector(UITextInput.caretRect(for:)) guard let originalMethod = class_getInstanceMethod(cls, sel) else {return} let originalIMP = method_getImplementation(originalMethod) typealias Function = @convention(c) (AnyObject, Selector, Any?) -> CGRect let function = unsafeBitCast(originalIMP, to: Function.self) let implementBlock: @convention(block) (UITextView, UITextPosition) -> CGRect = { (textView, position) -> CGRect in var rect = function(textView, sel, position) guard let parentView = textView.superview as? NextGrowingTextView else {return rect} guard let caretSize = parentView.caretSize else {return rect} rect.origin.y -= (caretSize.height - rect.size.height) rect.size = caretSize return rect } let types = "{CGRect={CGPoint=dd}{CGSize=dd}}@:@" class_addMethod(cls, sel, imp_implementationWithBlock(unsafeBitCast(implementBlock, to: AnyObject.self)), types) } } }
|
参考
每周 Swift 社区问答:@convention