黑魔法到底有多强大?(二)融云会话列表Cell标题显示富文本、添加图片

版权声明:欢迎大家积极分享!交流。关注我~ https://blog.csdn.net/qinqi376990311/article/details/81001450

黑魔法到底有多强大?

第二篇 融云会话列表Cell标题显示富文本、添加图片

TIPS:我们可能都看过无数的文章,讲解在OC中如何实现Method Swizzling 交换方法,但是在实际应用中,好多人可能想不到这一点。所以我准备写一系列利用黑魔法才能实现的需求的文章。

我的工程里接入了融云SDK,并使用了其界面,这样便于快速开发。
现在因为用户群体的区分,我们要求在昵称的后面,添加一个图片标识。

会话列表Cell

于是按照融云的教程,在控制器的
-willDisplayConversationTableCell:atIndexPath: 方法中,修改 cell 的 conversationTitle 这个 Label。

但是细心的人肯定会发现,第一次走这个方法的时候,conversationTitle 是没有 frame 或者 text 为空的。

之后我甚至给融云提交了工单,问他们,他们的回答是可以通过自定义会话列表的cell来实现我的需求。后来我想想,会话还有好多状态,比如聊天置顶,消息免打扰等等,很麻烦。于是我就打印了 RCConversationCell 的方法列表。于是就有了下文。

在 RCConversationCell 里面,除了 -setDataModel: 会修改conversationTitle 的 text 之外,还有 -onUserInfoUpdate: 这个通知的方法会修改。如此一来,我们只需要 hook 上面两个方法,再加上我们自己的判断,来确定是否添加图片就好了。

1、创建 RCConversationCell 的 Category,我这里命名为 RCConversationCell+Swizzling
2、重写 +load 方法,hook 上述两个方法,并在这两个方法执行完毕之后,添加我们的代码,上代码~

#import "RCConversationCell+Swizzling.h"

@implementation RCConversationCell (Swizzling)

+ (void)load {
    [super load];
    Method setDataOriginal = class_getInstanceMethod([self class], @selector(setDataModel:));
    Method setDataNew = class_getInstanceMethod([self class], @selector(swizzlingSetDataModel:));
    if (!class_addMethod([self class], @selector(setDataModel:), method_getImplementation(setDataNew), method_getTypeEncoding(setDataNew))) {
        method_exchangeImplementations(setDataOriginal, setDataNew);
    }
    Method userInfoOriginal = class_getInstanceMethod([self class], NSSelectorFromString(@"onUserInfoUpdate:"));
    Method userInfoNew = class_getInstanceMethod([self class], @selector(swizzlingOnUserInfoUpdate:));
    if (!class_addMethod([self class], NSSelectorFromString(@"onUserInfoUpdate:"), method_getImplementation(userInfoNew), method_getTypeEncoding(userInfoNew))) {
        method_exchangeImplementations(userInfoOriginal, userInfoNew);
    }
}

- (void)swizzlingOnUserInfoUpdate:(id)userInfo {
    [self swizzlingOnUserInfoUpdate:userInfo];
    dispatch_main_async_safe((^{
        [self configureConversationTitleLabel];
    }))
}

- (void)swizzlingSetDataModel:(RCConversationModel *)model {
    [self swizzlingSetDataModel:model];
    [self configureConversationTitleLabel];
}

- (void)configureConversationTitleLabel {
    NSString *originTitle = self.conversationTitle.text;
    if (!originTitle) {
        return;
    }
    self.conversationTitle.font = [UIFont systemFontOfSize:kFontSize(16)];
    self.conversationTitle.textColor = kBlackTextColor();
    [SCUserTool getUserInfoWithID:self.model.targetId refresh:NO complete:^(SCUser *user) {
        if (!user) {
            return;
        }
        NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:user.displayName];
        if (user.isCustomer) {
            self.conversationTitle.textColor = [UIColor colorWithHexString:@"#9013FE" alpha:1.0];
            NSTextAttachment *att = [[NSTextAttachment alloc] init];
            att.bounds = CGRectMake(0, kRealValue(-2), kRealValue(16), kRealValue(16));
            att.image = [UIImage imageNamed:kChatImageName(@"chat_service")];
            NSAttributedString *img = [NSAttributedString attributedStringWithAttachment:att];
            [str appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]];
            [str appendAttributedString:img];
        }
        if ([user.userId hasPrefix:@"agent"]) {
            self.conversationTitle.textColor = [UIColor colorWithHexString:@"#FFC700" alpha:1.0];
            NSTextAttachment *att = [[NSTextAttachment alloc] init];
            att.bounds = CGRectMake(0, kRealValue(-2), kRealValue(16), kRealValue(16));
            att.image = [UIImage imageNamed:kChatImageName(@"chat_delegate")];
            NSAttributedString *img = [NSAttributedString attributedStringWithAttachment:att];
            [str appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]];
            [str appendAttributedString:img];
        }
        self.conversationTitle.attributedText = str;
    }];
}

PS:使用 NSSelectorFromString 是因为 -onUserInfoUpdate 是私有方法。我打印了 RCConversationCell 的所有方法名,感觉有可能会修改 conversationTitle 的 text 的方法,然后慢慢试出来的。也不容易哈~

如此一来,就实现了回话列表中会话标题显示富文本的需求~

顺便提一下,在会话页面,导航标题也需要用富文本的话,可以通过设置 self.navigationItem.titleView 来实现。因为是 navigationItem ,所以不会影响下一个 push 或 pop 回去的控制器。

说到 UINavigationItem ,可以移步这里:
关于UINavigationBar 和 UINavigationItem
里面简单介绍了一下它的作用。

猜你喜欢

转载自blog.csdn.net/qinqi376990311/article/details/81001450