当前位置:   article > 正文

中文手写输入法闪退问题_ios17 中文输入法 导致闪退

ios17 中文输入法 导致闪退

近日有用户报 app 调用中文手写输入法时出现闪退。问题描述可以参照网上:

笔者的这个 App 中也是一样,使用了 +UITouch 分类重写了 ScrollView 的 touchesXXX 方法。
网上提到的解决办法都是千篇一律,即不要重写 ScrollView 的 touchesXXX 方法。但这个 app 中这是不可能的,因为笔者有一个自定义控件必须要让 scrollView 响应点击事件。

经过调试发现,这个崩溃是因为中文输入法中一个私有类 UIKBCandidateCollectionView(即显示候选词条的 bar)也是一个 UIScrollView ):

(lldb) cpo self
<UIKBCandidateCollectionView: 0x1040b5c00; frame = (0 0; 369 38); clipsToBounds = YES; opaque = NO; autoresize = LM+H; gestureRecognizers = <NSArray: 0x17424b4c0>; layer = <CALayer: 0x170225ac0>; contentOffset: {0, 0}; contentSize: {1003, 38}> collection view layout: <UICollectionViewFlowLayout: 0x103d4f090>

(lldb) cpo [self superclass]
UICollectionView

(lldb) cpo [[self superclass] superclass]
UIScrollView
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

而这个类的 nextResponder 是一个 UIKBHandwritingCandidateView:

(lldb) cpo [self nextResponder]
<UIKBHandwritingCandidateView: 0x10032ef90; frame = (0 0; 369 38); opaque = NO; layer = <CALayer: 0x170236dc0>>
  • 1
  • 2

而当 UIKBCandidateCollectionView 调用 nextResponder 的 touchesBegan:withEvent: 方法时就会 crash。

具体机制未细究,估计是 iOS 的 bug(有时间提给苹果吧)。于是解决办法就是修改 +UITouch 分类,在向 nextResponder 传递触摸事件之前做一个判断,发现是 UIKBCandidateCollectionView 类就不传递触摸事件:

#import "UIScrollView+UITouch.h"
#import <objc/runtime.h>

@implementation UIScrollView(UITouch)

-(NSString* )getClassName{
    return NSStringFromClass([self class]);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    if(![[self getClassName] hasPrefix:@"UIKB"]){
        [[self nextResponder] touchesBegan:touches withEvent:event];
    }
    [super touchesBegan:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if(![[self getClassName] hasPrefix:@"UIKB"]){
        [[self nextResponder] touchesMoved:touches withEvent:event];
    }
    [super touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if(![[self getClassName] hasPrefix:@"UIKB"]){
        [[self nextResponder] touchesEnded:touches withEvent:event];
    }
    [super touchesEnded:touches withEvent:event];
}


@end
  • 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

注意:Category 分类哪怕是不用导入头文件也会自动失效,这和普通类不一样(普通的类不导入头文件是不会加载的)。只不过如果你不导入分类的头文件的话,你无法在源代码中调用其扩展和覆盖的方法。但 +UITouch 这个分类不同,它的所有 touchesXXX 方法是触摸发生时自动调用的,不需要你在源代码中手动调用。

其实我们可以有另一种更好的选择,即继承 UIScrollView 子类,然后在子类中覆盖 touchesXXX 方法,从而避免在 Category 中使用私有 API,因为 UIKBCandidateCollectionView 类是苹果私有类,不能保证将来它还叫这个名字。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/509856
推荐阅读
相关标签
  

闽ICP备14008679号