适配

解决iOS14Emoji表情Search崩溃

2021-09-27  本文已影响0人  iOS_zy
IMG_53E7687592F7-1.jpeg

iOS 14 开始,系统的 emoji 键盘内部有一个搜索框 TUIEmojiSearchTextField,这个搜索框如果在 init 的时候设置 delegate(或者设置了keyboardAppearance) 会导致触发死循环,目前我们并不需要为这个新的系统TF做代理,所以需要过滤掉它。

我出错的位置是BlocksKit里面改用了“TUIEmojiSearchTextField”的delegate。BlocksKit会在把delegate变成block使用,非常方便,但是这里明显是转换了一个我们并不需要的delegate所以在BlocksKit获取delegate的地方过滤它。

通过断点,我发现会有一个TUIEmojiSearchTextField的delegate在“bk_registerDynamicDelegateNamed:forProtocol:”方法中被调用,它主要功能就是修改 getter 和 setter 方法,将原有的 delegate 转发到 realDelegate,修改原有的 delegate 的实现。下图即是bk_registerDynamicDelegateNamed:forProtocol方法。

+ (void)bk_registerDynamicDelegateNamed:(NSString *)delegateName forProtocol:(Protocol *)protocol
{
    NSMapTable *propertyMap = [self bk_delegateInfoByProtocol:YES];
    A2BlockDelegateInfo *infoAsPtr = (__bridge void *)[propertyMap objectForKey:protocol];
    if (infoAsPtr != NULL) { return; }

    const char *name = delegateName.UTF8String;
    objc_property_t property = class_getProperty(self, name);
    SEL setter = setterForProperty(property, name);
    SEL a2_setter = prefixedSelector(setter);
    SEL getter = getterForProperty(property, name);

    A2BlockDelegateInfo info = {
        setter, a2_setter, getter
    };

    [propertyMap setObject:(__bridge id)&info forKey:protocol];
    infoAsPtr = (__bridge void *)[propertyMap objectForKey:protocol];

    IMP setterImplementation = imp_implementationWithBlock(^(NSObject *delegatingObject, id delegate) {
        A2DynamicDelegate *dynamicDelegate = getDynamicDelegate(delegatingObject, protocol, infoAsPtr, YES);
        if ([delegate isEqual:dynamicDelegate]) {
            delegate = nil;
        }
        dynamicDelegate.realDelegate = delegate;
    });

    if (!swizzleWithIMP(self, setter, a2_setter, setterImplementation, "v@:@", YES)) {
        bzero(infoAsPtr, sizeof(A2BlockDelegateInfo));
        return;
    }

    if (![self instancesRespondToSelector:getter]) {
        IMP getterImplementation = imp_implementationWithBlock(^(NSObject *delegatingObject) {
            return [delegatingObject bk_dynamicDelegateForProtocol:a2_protocolForDelegatingObject(delegatingObject, protocol)];
        });

        addMethodWithIMP(self, getter, NULL, getterImplementation, "@@:", NO);
    }
}

在imp_implementationWithBlock中,加入判断代码:

if(@available(iOS 13.0, *)) {
          if([delegate isKindOfClass:NSClassFromString(@"TUIEmojiSearchTextField")]) {
              delegate = nil;
          }
        }

代码位置如下:


WX20210927-174752@2x.png

文章方法参考自腾讯的QMUI的1042问题:Tencent/QMUI_iOS/issues/1042

上一篇 下一篇

猜你喜欢

热点阅读