新浪微博客户端(57)-显示微博文本中的表情

DJEmotionTool.h

#import <Foundation/Foundation.h>

@class DJEmotion;
@interface DJEmotionTool : NSObject

/** 保存最近点击Emotion */
+ (void)saveRecentEmotion:(DJEmotion *)emotion;

/** 根据表情文件名获取对应的Emotion表情 */
+ (DJEmotion *)emotionWithChs:(NSString *)chs;



/** 获取存储在沙盒中最近点击的Emotion集合 */
+ (NSArray *)recentEmotions;
/** 获取默认表情 */
+ (NSArray *)defaultEmotions;
/** 获取Emoji表情 */
+ (NSArray *)emojiEmotions;
/** 获取浪小花表情 */
+ (NSArray *)lxhEmotions;

@end

DJEmotionTool.m

#import "DJEmotionTool.h"
#import "DJEmotion.h"
#import "MJExtension.h"



// 最近表情保存路径
#define DJEmotionPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"emotion.archiver"]

// 类似于java里面的静态成员变量
static NSMutableArray *_recentEmotions;

@implementation DJEmotionTool


static NSArray *_defaultEmotions, *_emojiEmotions, *_lxhEmotions;



/**
 * 这个方法会在第一次使用这个类的时候调一次,且只调一次
 * 类似于java中静态代码块
 */
+ (void)initialize {

    _recentEmotions = [NSKeyedUnarchiver unarchiveObjectWithFile:DJEmotionPath];
    if (_recentEmotions == nil) {
        _recentEmotions = [NSMutableArray array];
    }
}



/** 保存最近点击Emotion */
+ (void)saveRecentEmotion:(DJEmotion *)emotion {
    
    // 移除之前存储的相同Emotion
    [_recentEmotions removeObject:emotion];

    // 在数组的头部插入新的Emotion
    [_recentEmotions insertObject:emotion atIndex:0];
    
    // 保存当前数组
    [NSKeyedArchiver archiveRootObject:_recentEmotions toFile:DJEmotionPath];

}


/** 根据表情文件名获取对应的Emotion表情 */
+ (DJEmotion *)emotionWithChs:(NSString *)chs {


    /* 遍历当前表情数组,根据表情文字,获取对应的Emotion对象 */
    NSArray *defaultEmotions = [self defaultEmotions];
    for (DJEmotion *emotion in defaultEmotions) {
        if ([emotion.chs isEqualToString:chs]) {
            return emotion;
        }
    }
    
    NSArray *lxhEmotions = [self lxhEmotions];
    for (DJEmotion *emotion in lxhEmotions) {
        if ([emotion.chs isEqualToString:chs]) {
            return emotion;
        }
    }
    
    return nil;
}



/** 获取存储在沙盒中最近点击的Emotion集合 */
+ (NSArray *)recentEmotions {
    return _recentEmotions;
}


/** 获取默认表情 */
+ (NSArray *)defaultEmotions {

    if (!_defaultEmotions) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"EmotionIcons/default/info.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        // 将字典数组转换成模型数组
        _defaultEmotions = [DJEmotion mj_objectArrayWithKeyValuesArray:dictArray];
        
    }
    return _defaultEmotions;
    
}


/** 获取Emoji表情 */
+ (NSArray *)emojiEmotions {

    if (!_emojiEmotions) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"EmotionIcons/emoji/info.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        // 将字典数组转换成模型数组
        _emojiEmotions = [DJEmotion mj_objectArrayWithKeyValuesArray:dictArray];
        
    }
    return _emojiEmotions;

}


/** 获取浪小花表情 */
+ (NSArray *)lxhEmotions {

    if (!_lxhEmotions) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"EmotionIcons/lxh/info.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        // 将字典数组转换成模型数组
        _lxhEmotions = [DJEmotion mj_objectArrayWithKeyValuesArray:dictArray];
        
    }
    return _lxhEmotions;
    
}



@end
#import "DJEmotionTool.h"
#import "DJEmotion.h"
#import "MJExtension.h"



// 最近表情保存路径
#define DJEmotionPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"emotion.archiver"]

// 类似于java里面的静态成员变量
static NSMutableArray *_recentEmotions;

@implementation DJEmotionTool


static NSArray *_defaultEmotions, *_emojiEmotions, *_lxhEmotions;



/**
 * 这个方法会在第一次使用这个类的时候调一次,且只调一次
 * 类似于java中静态代码块
 */
+ (void)initialize {

    _recentEmotions = [NSKeyedUnarchiver unarchiveObjectWithFile:DJEmotionPath];
    if (_recentEmotions == nil) {
        _recentEmotions = [NSMutableArray array];
    }
}



/** 保存最近点击Emotion */
+ (void)saveRecentEmotion:(DJEmotion *)emotion {
    
    // 移除之前存储的相同Emotion
    [_recentEmotions removeObject:emotion];

    // 在数组的头部插入新的Emotion
    [_recentEmotions insertObject:emotion atIndex:0];
    
    // 保存当前数组
    [NSKeyedArchiver archiveRootObject:_recentEmotions toFile:DJEmotionPath];

}


/** 根据表情文件名获取对应的Emotion表情 */
+ (DJEmotion *)emotionWithChs:(NSString *)chs {


    /* 遍历当前表情数组,根据表情文字,获取对应的Emotion对象 */
    NSArray *defaultEmotions = [self defaultEmotions];
    for (DJEmotion *emotion in defaultEmotions) {
        if ([emotion.chs isEqualToString:chs]) {
            return emotion;
        }
    }
    
    NSArray *lxhEmotions = [self lxhEmotions];
    for (DJEmotion *emotion in lxhEmotions) {
        if ([emotion.chs isEqualToString:chs]) {
            return emotion;
        }
    }
    
    return nil;
}



/** 获取存储在沙盒中最近点击的Emotion集合 */
+ (NSArray *)recentEmotions {
    return _recentEmotions;
}


/** 获取默认表情 */
+ (NSArray *)defaultEmotions {

    if (!_defaultEmotions) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"EmotionIcons/default/info.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        // 将字典数组转换成模型数组
        _defaultEmotions = [DJEmotion mj_objectArrayWithKeyValuesArray:dictArray];
        
    }
    return _defaultEmotions;
    
}


/** 获取Emoji表情 */
+ (NSArray *)emojiEmotions {

    if (!_emojiEmotions) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"EmotionIcons/emoji/info.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        // 将字典数组转换成模型数组
        _emojiEmotions = [DJEmotion mj_objectArrayWithKeyValuesArray:dictArray];
        
    }
    return _emojiEmotions;

}


/** 获取浪小花表情 */
+ (NSArray *)lxhEmotions {

    if (!_lxhEmotions) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"EmotionIcons/lxh/info.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        // 将字典数组转换成模型数组
        _lxhEmotions = [DJEmotion mj_objectArrayWithKeyValuesArray:dictArray];
        
    }
    return _lxhEmotions;
    
}



@end

DJEmotionKeyboard.m

- (DJEmotionListView *)defaultEmotionView {

    if (!_defaultEmotionView) {
        
        DJEmotionListView *defaultEmotionView = [[DJEmotionListView alloc] init];
        _defaultEmotionView = defaultEmotionView;
        defaultEmotionView.emotions = [DJEmotionTool defaultEmotions];
        
    }
    return _defaultEmotionView;

}



- (DJEmotionListView *)emojiEmotionView {

    if (!_emojiEmotionView) {
        DJEmotionListView *emojiEmotionView = [[DJEmotionListView alloc] init];
        _emojiEmotionView = emojiEmotionView;
        emojiEmotionView.emotions = [DJEmotionTool emojiEmotions];
    }
    
    return _emojiEmotionView;

}


- (DJEmotionListView *)lxhEmotionView {

    if (!_lxhEmotionView) {
        DJEmotionListView *lxhEmotionView = [[DJEmotionListView alloc] init];
        _lxhEmotionView = lxhEmotionView;
        lxhEmotionView.emotions = [DJEmotionTool lxhEmotions];
    }
    return _lxhEmotionView;
}

DJStatus.m

// 取出数组中的文本块进行拼接
    for (DJStatusPart *part in statusParts) {
     
        NSAttributedString *subString = nil;
        if (part.isSpecial) { // 判断是否是特殊文本(若是特殊文本,则进行特殊处理,超链接:变色,表情文本:更换成表情图片)
            if (part.isEmotion) { // 判断当前文本块是否是表情
                
                DJEmotion *emotion = [DJEmotionTool emotionWithChs:part.text];
                if (emotion) { // 找到了当前文本对应的Emotion表情
                    NSString *emotionName = emotion.png;
                    NSString *imageName = nil;
                    
                    if ([emotionName hasPrefix:@"d_"] || [emotionName hasPrefix:@"f_"] ||
                        [emotionName hasPrefix:@"h_"] || [emotionName hasPrefix:@"l_"] || [emotionName hasPrefix:@"o_"] || [emotionName hasPrefix:@"w_"]) { // 默认表情
                        imageName = [NSString stringWithFormat:@"EmotionIcons/default/%@",emotion.png];
                    } else if ([emotionName hasPrefix:@"lxh_"]) { // 浪小花表情
                        imageName = [NSString stringWithFormat:@"EmotionIcons/lxh/%@",emotion.png];
                    }
                    
                    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
                    attachment.image = [UIImage imageNamed:imageName];
                    attachment.bounds = CGRectMake(0, -4, 16, 16);
                    subString = [NSAttributedString attributedStringWithAttachment:attachment];

                } else {
                    // 未在plist列表中找到对应表情,或该表情为Emoji
                    subString = [[NSAttributedString alloc] initWithString:part.text];
                }
                
            } else { // 超链接&昵称
                subString = [[NSAttributedString alloc] initWithString:part.text attributes:@{NSForegroundColorAttributeName : [UIColor blueColor]}];
            }
        } else { // 不做任何处理
            subString = [[NSAttributedString alloc] initWithString:part.text];
        }

        [attributedText appendAttributedString:subString];

最终效果:

新浪微博客户端(57)-显示微博文本中的表情