//
|
// HMEmoticonManager.m
|
// 表情键盘
|
//
|
// Created by 刘凡 on 16/3/3.
|
// Copyright © 2016年 itcast. All rights reserved.
|
//
|
|
#import "HMEmoticonManager.h"
|
#import "NSBundle+HMEmoticon.h"
|
#import "HMEmoticonAttachment.h"
|
|
/// 每页显示的表情数量
|
static NSInteger kEmoticonsCountOfPage = 20;
|
/// 命名空间常量
|
NSString *const HMEmoticonNamespace = @"cn.itcast";
|
/// 默认用户标识符
|
NSString *const HMEmoticonDefaultUserIdentifier = @"DefaultUser";
|
/// 表情文件名
|
NSString *const HMEmoticonFileName = @".emoticons.json";
|
|
@implementation HMEmoticonManager {
|
NSMutableArray <HMEmoticon *> *_recentEmoticonList;
|
}
|
|
#pragma mark - 单例 & 构造函数
|
+ (instancetype)sharedManager {
|
static id instance;
|
|
static dispatch_once_t onceToken;
|
dispatch_once(&onceToken, ^{
|
instance = [[self alloc] init];
|
});
|
|
return instance;
|
}
|
|
- (instancetype)init {
|
self = [super init];
|
if (self) {
|
_packages = [NSMutableArray array];
|
|
[self loadPackages];
|
}
|
return self;
|
}
|
|
#pragma mark - 字符串转换
|
- (NSAttributedString *)emoticonStringWithString:(NSString *)string font:(UIFont *)font textColor:(UIColor *)textColor {
|
|
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]
|
initWithString:string
|
attributes:@{NSFontAttributeName: font,
|
NSForegroundColorAttributeName: textColor}];
|
|
NSString *pattern = @"\\[.*?\\]";
|
NSRegularExpression *regx = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL];
|
|
NSArray *matches = [regx matchesInString:string options:0 range:NSMakeRange(0, string.length)];
|
for (NSTextCheckingResult *result in matches.reverseObjectEnumerator) {
|
|
NSRange range = [result rangeAtIndex:0];
|
NSString *str = [string substringWithRange:range];
|
|
HMEmoticon *emoticon = [self emoticonWithString:str];
|
if (emoticon != nil) {
|
NSAttributedString *emoticonString = [HMEmoticonAttachment emoticonStringWithEmoticon:emoticon font:font textColor:textColor];
|
|
[attributedString replaceCharactersInRange:range withAttributedString:emoticonString];
|
}
|
}
|
|
return attributedString.copy;
|
}
|
|
- (HMEmoticon *)emoticonWithString:(NSString *)string {
|
|
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"chs == %@", string];
|
HMEmoticon *emoticon = nil;
|
|
for (NSInteger i = 1; i < _packages.count; i++) {
|
|
HMEmoticonPackage *package = _packages[i];
|
|
NSArray *filter = [package.emoticonsList filteredArrayUsingPredicate:predicate];
|
|
if (filter.count == 1) {
|
emoticon = filter[0];
|
|
break;
|
}
|
}
|
|
return emoticon;
|
}
|
|
#pragma mark - 数据源方法
|
- (NSInteger)numberOfPagesInSection:(NSInteger)section {
|
HMEmoticonPackage *package = _packages[section];
|
|
return ((NSInteger)package.emoticonsList.count - 1) / kEmoticonsCountOfPage + 1;
|
}
|
|
- (NSArray *)emoticonsWithIndexPath:(NSIndexPath *)indexPath {
|
HMEmoticonPackage *package = self.packages[indexPath.section];
|
|
NSInteger location = indexPath.item * kEmoticonsCountOfPage;
|
NSInteger length = kEmoticonsCountOfPage;
|
|
// 判断是否越界
|
if ((location + length) > package.emoticonsList.count) {
|
length = package.emoticonsList.count - location;
|
}
|
|
NSRange range = NSMakeRange(location, length);
|
|
return [package.emoticonsList subarrayWithRange:range];
|
}
|
|
#pragma mark - 最近使用表情
|
- (void)addRecentEmoticon:(HMEmoticon *)emoticon {
|
// 0. 表情计数 ++
|
emoticon.times++;
|
|
// 1. 判断表情是否已经存在
|
if (![_recentEmoticonList containsObject:emoticon]) {
|
[_recentEmoticonList addObject:emoticon];
|
}
|
|
// 2. 排序
|
[_recentEmoticonList sortUsingComparator:^NSComparisonResult(HMEmoticon *obj1, HMEmoticon *obj2) {
|
return obj1.times < obj2.times;
|
}];
|
|
// 3. 更新最近表情包
|
[self updateRecentPackage];
|
|
// 4. 保存表情包
|
[self saveRecentEmoticonList];
|
}
|
|
/// 更新最近表情包数组
|
- (void)updateRecentPackage {
|
NSInteger length = _recentEmoticonList.count < kEmoticonsCountOfPage ? _recentEmoticonList.count : kEmoticonsCountOfPage;
|
|
_packages[0].emoticonsList = [_recentEmoticonList subarrayWithRange:NSMakeRange(0, length)].mutableCopy;
|
}
|
|
/// 保存最近表情数组
|
- (void)saveRecentEmoticonList {
|
|
NSMutableArray *jsonDict = [NSMutableArray array];
|
for (HMEmoticon *emoticon in _recentEmoticonList) {
|
[jsonDict addObject:[emoticon dictionary]];
|
}
|
|
NSData *data = [NSJSONSerialization dataWithJSONObject:jsonDict options:NSJSONWritingPrettyPrinted error:NULL];
|
[data writeToFile:[self filePathForRecentEmoticon] atomically:YES];
|
}
|
|
/// 加载最近表情数组
|
///
|
/// @return 最近表情数组
|
- (NSMutableArray <HMEmoticon *>*)loadRecentEmoticonList {
|
|
NSMutableArray *arrayM = [NSMutableArray array];
|
NSData *data = [NSData dataWithContentsOfFile:[self filePathForRecentEmoticon]];
|
|
if (data == nil) {
|
return arrayM;
|
}
|
|
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
|
|
for (NSDictionary *dict in array) {
|
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"chs CONTAINS %@ || code CONTAINS %@", dict[@"chs"], dict[@"code"]];
|
|
for (NSInteger i = 1; i < _packages.count; i++) {
|
HMEmoticonPackage *package = _packages[i];
|
|
NSArray *filter = [package.emoticonsList filteredArrayUsingPredicate:predicate];
|
|
if (filter.count == 1) {
|
[arrayM addObject:filter[0]];
|
break;
|
}
|
}
|
}
|
|
return arrayM;
|
}
|
|
/// 最近表情文件路径
|
- (NSString *)filePathForRecentEmoticon {
|
NSString *dir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
|
|
return [[dir stringByAppendingPathComponent:self.userIdentifier] stringByAppendingString:HMEmoticonFileName];
|
}
|
|
#pragma mark - 加载表情包数据
|
- (void)loadPackages {
|
|
// 1. 读取 emoticons.plist
|
NSString *path = [[NSBundle hm_emoticonBundle] pathForResource:@"emoticons.plist" ofType:nil];
|
NSArray *array = [NSArray arrayWithContentsOfFile:path];
|
|
// 2. 遍历数组,生成 packages 模型
|
for (NSDictionary *dict in array) {
|
[_packages addObject:[HMEmoticonPackage packageWithDict:dict]];
|
}
|
|
// 3. 加载最近使用表情列表
|
_recentEmoticonList = [self loadRecentEmoticonList];
|
|
// 4. 更新最近表情包
|
[self updateRecentPackage];
|
}
|
|
#pragma mark - 用户标识符
|
@synthesize userIdentifier = _userIdentifier;
|
- (void)setUserIdentifier:(NSString *)userIdentifier {
|
_userIdentifier = userIdentifier.copy;
|
|
_recentEmoticonList = [self loadRecentEmoticonList];
|
[self updateRecentPackage];
|
}
|
|
- (NSString *)userIdentifier {
|
if (_userIdentifier == nil) {
|
_userIdentifier = HMEmoticonDefaultUserIdentifier;
|
}
|
return [NSString stringWithFormat:@"%@.%@", HMEmoticonNamespace, _userIdentifier];;
|
}
|
|
@end
|