Objective-C开发iOS15应用在文本框输入特殊字符时崩溃如何解决
iOS15 文本框输入特殊字符崩溃问题解决方案
问题根因分析
该崩溃是iOS15.x系统专属的原生文本控件bug,触发场景为:当UITextField/UITextView开启了自动校正、拼写检查功能时,用户输入特殊字符(含emoji、全角符号、特殊标点等),系统内部调用私有方法_drawTexCorrectionMarker:characterRange:atOrigin:graphicsContext:绘制文本校正标记时,计算得到了无效的越界字符范围{0, 0},触发一致性校验异常导致崩溃。
错误截图如下:
核心错误日志:
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'out of bounds characterRange {0, 0} specified to _drawTexCorrectionMarker:characterRange:atOrigin:graphicsContext:' terminating with uncaught exception of type NSException
可行解决方案
方案1:关闭文本控件的自动校正能力(推荐,适配成本最低)
如果业务不需要自动拼写校正功能,可以直接关闭对应控件的自动校正和拼写检查属性,完全规避该问题:
- 针对单个
UITextField/UITextView设置:
// 仅对iOS15版本做特殊处理,更高版本保留系统原生功能 if (@available(iOS 15.0, *)) { textField.autocorrectionType = UITextAutocorrectionTypeNo; textField.spellCheckingType = UITextSpellCheckingTypeNo; // UITextView同理设置 textView.autocorrectionType = UITextAutocorrectionTypeNo; textView.spellCheckingType = UITextSpellCheckingTypeNo; }
- 全局统一适配所有文本控件:
if (@available(iOS 15.0, *)) { [[UITextField appearance] setAutocorrectionType:UITextAutocorrectionTypeNo]; [[UITextField appearance] setSpellCheckingType:UITextSpellCheckingTypeNo]; [[UITextView appearance] setAutocorrectionType:UITextAutocorrectionTypeNo]; [[UITextView appearance] setSpellCheckingType:UITextSpellCheckingTypeNo]; }
方案2:Hook系统私有方法做容错(适用于需要保留自动校正功能的场景)
通过Runtime方法交换,在系统调用崩溃方法前先做参数合法性校验,无效范围直接跳过执行:
#import <objc/runtime.h> @implementation UIView (iOS15TextFix) + (void)load { if (@available(iOS 15.0, *)) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class clazz = NSClassFromString(@"UITextInputView"); SEL originalSel = NSSelectorFromString(@"_drawTexCorrectionMarker:characterRange:atOrigin:graphicsContext:"); SEL swizzledSel = @selector(ss_drawTexCorrectionMarker:characterRange:atOrigin:graphicsContext:); Method originalMethod = class_getInstanceMethod(clazz, originalSel); Method swizzledMethod = class_getInstanceMethod(self, swizzledSel); if (originalMethod && swizzledMethod) { method_exchangeImplementations(originalMethod, swizzledMethod); } }); } } - (void)ss_drawTexCorrectionMarker:(id)marker characterRange:(NSRange)range atOrigin:(CGPoint)origin graphicsContext:(id)context { // 校验range合法性,无效范围直接返回不执行原逻辑 if (range.location == NSNotFound || range.length == 0) { return; } [self ss_drawTexCorrectionMarker:marker characterRange:range atOrigin:origin graphicsContext:context]; } @end
内容的提问来源于stack exchange,提问作者Vijay Kahar
相关产品推荐
相关产品推荐

