Commit 7a241735970efcd85d5713572e82202b028c57f1
0.1.9 ,增加Emoji表情
| @@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
| 8 | 8 | ||
| 9 | Pod::Spec.new do |s| | 9 | Pod::Spec.new do |s| |
| 10 | s.name = 'CNLiveBusinessTools' | 10 | s.name = 'CNLiveBusinessTools' |
| 11 | - s.version = '0.1.8' | 11 | + s.version = '0.1.9' |
| 12 | s.summary = '业务工具集合组件.' | 12 | s.summary = '业务工具集合组件.' |
| 13 | 13 | ||
| 14 | # This description is used to generate tags and improve search results. | 14 | # This description is used to generate tags and improve search results. |
| @@ -35,6 +35,9 @@ Pod::Spec.new do |s| | @@ -35,6 +35,9 @@ Pod::Spec.new do |s| | ||
| 35 | # s.resource_bun/Users/open/CNLiveBaseKit/CNLiveBaseKit.podspecdles = { | 35 | # s.resource_bun/Users/open/CNLiveBaseKit/CNLiveBaseKit.podspecdles = { |
| 36 | # 'CNLiveBusinessTools' => ['CNLiveBusinessTools/Assets/*.png'] | 36 | # 'CNLiveBusinessTools' => ['CNLiveBusinessTools/Assets/*.png'] |
| 37 | # } | 37 | # } |
| 38 | + s.resource_bundles = { | ||
| 39 | + 'CNLiveBusinessTools' => ['CNLiveBusinessTools/Assets/*.bundle'] | ||
| 40 | + } | ||
| 38 | 41 | ||
| 39 | # s.public_header_files = 'Pod/Classes/**/*.h' | 42 | # s.public_header_files = 'Pod/Classes/**/*.h' |
| 40 | s.frameworks = 'UIKit', 'MapKit','Photos' | 43 | s.frameworks = 'UIKit', 'MapKit','Photos' |
| @@ -42,5 +45,6 @@ Pod::Spec.new do |s| | @@ -42,5 +45,6 @@ Pod::Spec.new do |s| | ||
| 42 | s.dependency 'CNLiveUserManagement' | 45 | s.dependency 'CNLiveUserManagement' |
| 43 | s.dependency 'CNLiveBaseKit' | 46 | s.dependency 'CNLiveBaseKit' |
| 44 | s.dependency 'CNLiveRequestBastKit' | 47 | s.dependency 'CNLiveRequestBastKit' |
| 45 | - | 48 | + s.dependency 'CNLiveTripartiteManagement/QMUIKit' |
| 49 | + | ||
| 46 | end | 50 | end |
8.13 KB
8.53 KB
8.35 KB
8.45 KB
8.59 KB
8.62 KB
7.69 KB
7.6 KB
8.49 KB
7.71 KB
8.35 KB
8.31 KB
7.83 KB
8.23 KB
8.51 KB
5.86 KB
7.07 KB
8.3 KB
8.32 KB
8.81 KB
8.8 KB
8.58 KB
8.61 KB
8.87 KB
8.75 KB
8.19 KB
9.02 KB
8.3 KB
8.96 KB
6.24 KB
6.24 KB
5.37 KB
7.89 KB
8.6 KB
7.71 KB
7.46 KB
8.37 KB
8.16 KB
8.27 KB
8.15 KB
7.92 KB
8.32 KB
7.9 KB
8.63 KB
8.42 KB
8.53 KB
8.64 KB
7.75 KB
8.17 KB
7.03 KB
8.3 KB
8.4 KB
8.72 KB
8.46 KB
8.61 KB
8.86 KB
8.31 KB
7.32 KB
6.79 KB
8.94 KB
7.98 KB
8.64 KB
8.44 KB
8.49 KB
8.3 KB
8.31 KB
8.11 KB
8.02 KB
8.06 KB
7.8 KB
8.13 KB
7.73 KB
8.28 KB
8.42 KB
7.99 KB
8.03 KB
8.63 KB
8.41 KB
6.77 KB
7.27 KB
7.37 KB
7.07 KB
7.17 KB
7.76 KB
7.15 KB
7.76 KB
7.58 KB
6.84 KB
6.43 KB
6.13 KB
6.41 KB
6.99 KB
7.82 KB
5.71 KB
8.69 KB
6.45 KB
6.32 KB
7.65 KB
7.71 KB
6.75 KB
7.88 KB
8.3 KB
7.2 KB
4.37 KB
6.55 KB
8.23 KB
6.59 KB
7.81 KB
7.78 KB
7.35 KB
7.05 KB
7.51 KB
6.88 KB
7.25 KB
6.8 KB
7.88 KB
8.58 KB
8.26 KB
8.52 KB
7.86 KB
8.82 KB
8.66 KB
7.58 KB
8.17 KB
7.32 KB
7.05 KB
8.14 KB
| 1 | -// | ||
| 2 | -// CNLiveBusinessTools.h | ||
| 3 | -// CNLiveBusinessTools | ||
| 4 | -// | ||
| 5 | -// Created by open on 2019/5/8. | ||
| 6 | -// | 1 | +// 业务模块工具 |
| 7 | 2 | ||
| 8 | -#import <Foundation/Foundation.h> | 3 | +#import "HttpService.h" |
| 4 | +#import "CNLiveNetBusinessTools.h" | ||
| 5 | +#import "CNLiveQQEmotionManager.h" | ||
| 6 | +#import "CNLiveEmotionHelper.h" | ||
| 7 | +#import "QMUIEmotion+CNLiveEmotion.h" | ||
| 9 | 8 | ||
| 10 | -NS_ASSUME_NONNULL_BEGIN | ||
| 11 | -typedef NS_ENUM(NSInteger, CNStatType) { | ||
| 12 | - CNStatTypeContentCount = 0, //内容次数统计 | ||
| 13 | - CNStatTypeContentDuration, //内容时长统计 | ||
| 14 | - CNStatTypeShareCount //分享次数统计 | ||
| 15 | -}; | ||
| 16 | -#pragma mark 文件类型 | ||
| 17 | -typedef NS_ENUM(NSInteger, CNFileType) { | ||
| 18 | - CNFileTypeReadAndLook = 0,//识别和预览 | ||
| 19 | - CNFileTypeOnlyRead, //只能识别,不能预览 | ||
| 20 | - CNFileTypeUnkown, //未知文件 | ||
| 21 | -}; | ||
| 22 | -@interface CNLiveBusinessTools : NSObject | ||
| 23 | -#pragma mark -- 统计 | ||
| 24 | -/** | ||
| 25 | - 统计eventId | ||
| 26 | - | ||
| 27 | - @param statType 统计类型 | ||
| 28 | - @param type 内容类型 例如:szzg/sxzg/daren/app | ||
| 29 | - @param userId 用户Id | ||
| 30 | - @C端/B端 | ||
| 31 | - @return eventId | ||
| 32 | - */ | ||
| 33 | -+ (NSString *)cnStatWithType:(CNStatType)statType type:(NSString *)type userId:(NSString *)userId programId:(NSString *)programId title:(NSString *)title; | ||
| 34 | -// 分享单独使用 | ||
| 35 | -+ (NSString *)cnStatWithType:(CNStatType)statType type:(NSString *)type userId:(NSString *)userId programId:(NSString *)programId title:(NSString *)title shareToType:(NSString *)shareToType; | ||
| 36 | - | ||
| 37 | -#pragma mark -- | ||
| 38 | -#pragma mark -- UUID | ||
| 39 | -// 获取UUID | ||
| 40 | -+ (NSString *)getUidForStat:(NSDate *)date; | ||
| 41 | -#pragma mark -- | ||
| 42 | -#pragma mark -- 获取 GIF 处理 | ||
| 43 | -+ (BOOL)isGif:(id)asset; | ||
| 44 | -+ (BOOL)isGifWithImageData: (NSData *)data; | ||
| 45 | -#pragma mark -- | ||
| 46 | -#pragma mark -- 文件 | ||
| 47 | -///文件类型 | ||
| 48 | -+ (NSDictionary *)fileTypeDic; | ||
| 49 | -//通过文件后缀名判断是否为可读文件 | ||
| 50 | -+ (CNFileType)isReadedFileByType:(NSString *)suffixType; | ||
| 51 | -#pragma mark -- | ||
| 52 | -#pragma mark -- 拼接需要的参数 | ||
| 53 | -+ (NSString *)uuid; | ||
| 54 | -+ (NSString *)getSpid; | ||
| 55 | -+ (NSString *)getSidIdfv; | ||
| 56 | -#pragma mark -- | ||
| 57 | -#pragma mark -- | ||
| 58 | -+ (NSString *)signvalue:(NSDictionary *)parameter; | ||
| 59 | -+ (NSString *)sha1:(NSString *)string; | ||
| 60 | - | ||
| 61 | -//sha1签名 | ||
| 62 | -+ (NSMutableDictionary *_Nullable)encryptionSignWithParameter:(NSMutableDictionary *_Nullable)parameter encryptionKey:(NSString *_Nullable)encryptionKey; | ||
| 63 | -#pragma mark -- | ||
| 64 | -#pragma mark -- 缓存 | ||
| 65 | -/** | ||
| 66 | - GIF表情存放位置 | ||
| 67 | - @return 地址 | ||
| 68 | - */ | ||
| 69 | -+ (NSString *)newChatGifFacePath; | ||
| 70 | -/** | ||
| 71 | - @param userId 单聊为对方ID,群聊为群聊 ID,图片和视频存放位置 | ||
| 72 | - @return 地址 | ||
| 73 | - */ | ||
| 74 | -+ (NSString *)newChatFilePathByUserId:(NSString *)userId; | ||
| 75 | - | ||
| 76 | -+ (nullable NSString *)chatFileWithCachePathByUserId:(NSString *_Nonnull)userId; | ||
| 77 | - | ||
| 78 | -//用户ID | ||
| 79 | -+ (nullable NSString *)chatFilePathByUserId:(NSString *_Nonnull)userId; | ||
| 80 | - | ||
| 81 | -/** | ||
| 82 | - @param userId 单聊为对方ID,群聊为群聊 ID | ||
| 83 | - @return 返回聊天发送的文件 所保存的文件夹地址 | ||
| 84 | - */ | ||
| 85 | -+ (NSString *)getChatFilesPathByUserId:(NSString *)userId; | ||
| 86 | - | ||
| 87 | -/** | ||
| 88 | - 0 | ||
| 89 | - @param userId 单聊为对方ID,群聊为群聊 ID ,语音文件保存路径 | ||
| 90 | - */ | ||
| 91 | -+ (NSString *)audioChatFilePathByUserId:(NSString *)userId; | ||
| 92 | - | ||
| 93 | -/** | ||
| 94 | - 聊天背景图图片地址 | ||
| 95 | - | ||
| 96 | - @return file | ||
| 97 | - */ | ||
| 98 | -+ (NSString *)chatBackgroupImagefilePath; | ||
| 99 | -#pragma mark -- | ||
| 100 | -@end | ||
| 101 | - | ||
| 102 | -NS_ASSUME_NONNULL_END |
| 1 | +// | ||
| 2 | +// CNLiveNetBusinessTools.h | ||
| 3 | +// CNLiveNetBusinessTools | ||
| 4 | +// | ||
| 5 | +// Created by 张旭 on 2020/4/14. | ||
| 6 | +// | ||
| 7 | + | ||
| 8 | +#import <Foundation/Foundation.h> | ||
| 9 | + | ||
| 10 | +NS_ASSUME_NONNULL_BEGIN | ||
| 11 | +typedef NS_ENUM(NSInteger, CNStatType) { | ||
| 12 | + CNStatTypeContentCount = 0, //内容次数统计 | ||
| 13 | + CNStatTypeContentDuration, //内容时长统计 | ||
| 14 | + CNStatTypeShareCount //分享次数统计 | ||
| 15 | +}; | ||
| 16 | +#pragma mark 文件类型 | ||
| 17 | +typedef NS_ENUM(NSInteger, CNFileType) { | ||
| 18 | + CNFileTypeReadAndLook = 0,//识别和预览 | ||
| 19 | + CNFileTypeOnlyRead, //只能识别,不能预览 | ||
| 20 | + CNFileTypeUnkown, //未知文件 | ||
| 21 | +}; | ||
| 22 | +@interface CNLiveNetBusinessTools : NSObject | ||
| 23 | +#pragma mark -- 统计 | ||
| 24 | +/** | ||
| 25 | + 统计eventId | ||
| 26 | + | ||
| 27 | + @param statType 统计类型 | ||
| 28 | + @param type 内容类型 例如:szzg/sxzg/daren/app | ||
| 29 | + @param userId 用户Id | ||
| 30 | + @C端/B端 | ||
| 31 | + @return eventId | ||
| 32 | + */ | ||
| 33 | ++ (NSString *)cnStatWithType:(CNStatType)statType type:(NSString *)type userId:(NSString *)userId programId:(NSString *)programId title:(NSString *)title; | ||
| 34 | +// 分享单独使用 | ||
| 35 | ++ (NSString *)cnStatWithType:(CNStatType)statType type:(NSString *)type userId:(NSString *)userId programId:(NSString *)programId title:(NSString *)title shareToType:(NSString *)shareToType; | ||
| 36 | + | ||
| 37 | +#pragma mark -- | ||
| 38 | +#pragma mark -- UUID | ||
| 39 | +// 获取UUID | ||
| 40 | ++ (NSString *)getUidForStat:(NSDate *)date; | ||
| 41 | +#pragma mark -- | ||
| 42 | +#pragma mark -- 获取 GIF 处理 | ||
| 43 | ++ (BOOL)isGif:(id)asset; | ||
| 44 | ++ (BOOL)isGifWithImageData: (NSData *)data; | ||
| 45 | +#pragma mark -- | ||
| 46 | +#pragma mark -- 文件 | ||
| 47 | +///文件类型 | ||
| 48 | ++ (NSDictionary *)fileTypeDic; | ||
| 49 | +//通过文件后缀名判断是否为可读文件 | ||
| 50 | ++ (CNFileType)isReadedFileByType:(NSString *)suffixType; | ||
| 51 | +#pragma mark -- | ||
| 52 | +#pragma mark -- 拼接需要的参数 | ||
| 53 | ++ (NSString *)uuid; | ||
| 54 | ++ (NSString *)getSpid; | ||
| 55 | ++ (NSString *)getSidIdfv; | ||
| 56 | +#pragma mark -- | ||
| 57 | +#pragma mark -- | ||
| 58 | ++ (NSString *)signvalue:(NSDictionary *)parameter; | ||
| 59 | ++ (NSString *)sha1:(NSString *)string; | ||
| 60 | + | ||
| 61 | +//sha1签名 | ||
| 62 | ++ (NSMutableDictionary *_Nullable)encryptionSignWithParameter:(NSMutableDictionary *_Nullable)parameter encryptionKey:(NSString *_Nullable)encryptionKey; | ||
| 63 | +#pragma mark -- | ||
| 64 | +#pragma mark -- 缓存 | ||
| 65 | +/** | ||
| 66 | + GIF表情存放位置 | ||
| 67 | + @return 地址 | ||
| 68 | + */ | ||
| 69 | ++ (NSString *)newChatGifFacePath; | ||
| 70 | +/** | ||
| 71 | + @param userId 单聊为对方ID,群聊为群聊 ID,图片和视频存放位置 | ||
| 72 | + @return 地址 | ||
| 73 | + */ | ||
| 74 | ++ (NSString *)newChatFilePathByUserId:(NSString *)userId; | ||
| 75 | + | ||
| 76 | ++ (nullable NSString *)chatFileWithCachePathByUserId:(NSString *_Nonnull)userId; | ||
| 77 | + | ||
| 78 | +//用户ID | ||
| 79 | ++ (nullable NSString *)chatFilePathByUserId:(NSString *_Nonnull)userId; | ||
| 80 | + | ||
| 81 | +/** | ||
| 82 | + @param userId 单聊为对方ID,群聊为群聊 ID | ||
| 83 | + @return 返回聊天发送的文件 所保存的文件夹地址 | ||
| 84 | + */ | ||
| 85 | ++ (NSString *)getChatFilesPathByUserId:(NSString *)userId; | ||
| 86 | + | ||
| 87 | +/** | ||
| 88 | + 0 | ||
| 89 | + @param userId 单聊为对方ID,群聊为群聊 ID ,语音文件保存路径 | ||
| 90 | + */ | ||
| 91 | ++ (NSString *)audioChatFilePathByUserId:(NSString *)userId; | ||
| 92 | + | ||
| 93 | +/** | ||
| 94 | + 聊天背景图图片地址 | ||
| 95 | + | ||
| 96 | + @return file | ||
| 97 | + */ | ||
| 98 | ++ (NSString *)chatBackgroupImagefilePath; | ||
| 99 | +#pragma mark -- | ||
| 100 | +@end | ||
| 101 | + | ||
| 102 | +NS_ASSUME_NONNULL_END |
| 1 | // | 1 | // |
| 2 | -// CNLiveBusinessTools.m | ||
| 3 | -// CNLiveBusinessTools | 2 | +// CNLiveNetBusinessTools.m |
| 3 | +// CNLiveNetBusinessTools | ||
| 4 | // | 4 | // |
| 5 | -// Created by open on 2019/5/8. | 5 | +// Created by 张旭 on 2020/4/14. |
| 6 | // | 6 | // |
| 7 | 7 | ||
| 8 | -#import "CNLiveBusinessTools.h" | 8 | +#import "CNLiveNetBusinessTools.h" |
| 9 | #import <Photos/Photos.h> | 9 | #import <Photos/Photos.h> |
| 10 | #import <CNLiveEnvironment/CNLiveEnvironment.h> | 10 | #import <CNLiveEnvironment/CNLiveEnvironment.h> |
| 11 | #import <CNLiveUserManagement/CNUserInfoManager.h> | 11 | #import <CNLiveUserManagement/CNUserInfoManager.h> |
| 12 | #import "CommonCrypto/CommonDigest.h" | 12 | #import "CommonCrypto/CommonDigest.h" |
| 13 | #import <CNLiveBaseKit/CNLiveBaseKit.h> | 13 | #import <CNLiveBaseKit/CNLiveBaseKit.h> |
| 14 | -@implementation CNLiveBusinessTools | 14 | +@implementation CNLiveNetBusinessTools |
| 15 | 15 | ||
| 16 | + (NSString *)cnStatWithType:(CNStatType)statType type:(NSString *)type userId:(NSString *)userId programId:(NSString *)programId title:(NSString *)title { | 16 | + (NSString *)cnStatWithType:(CNStatType)statType type:(NSString *)type userId:(NSString *)userId programId:(NSString *)programId title:(NSString *)title { |
| 17 | 17 | ||
| @@ -271,10 +271,10 @@ | @@ -271,10 +271,10 @@ | ||
| 271 | } | 271 | } |
| 272 | + (CNFileType)isReadedFileByType:(NSString *)suffixType | 272 | + (CNFileType)isReadedFileByType:(NSString *)suffixType |
| 273 | { | 273 | { |
| 274 | - if ([[CNLiveBusinessTools fileTypeDic] objectForKey:[NSString stringWithFormat:@".%@",suffixType]]) { | 274 | + if ([[CNLiveNetBusinessTools fileTypeDic] objectForKey:[NSString stringWithFormat:@".%@",suffixType]]) { |
| 275 | return CNFileTypeReadAndLook; | 275 | return CNFileTypeReadAndLook; |
| 276 | } | 276 | } |
| 277 | - else if ([[CNLiveBusinessTools onlyReadFileType] objectForKey:[NSString stringWithFormat:@".%@",suffixType]]) | 277 | + else if ([[CNLiveNetBusinessTools onlyReadFileType] objectForKey:[NSString stringWithFormat:@".%@",suffixType]]) |
| 278 | { | 278 | { |
| 279 | return CNFileTypeOnlyRead; | 279 | return CNFileTypeOnlyRead; |
| 280 | } | 280 | } |
| @@ -362,7 +362,7 @@ | @@ -362,7 +362,7 @@ | ||
| 362 | [muDic setObject:AppVersion forKey:@"ver"]; | 362 | [muDic setObject:AppVersion forKey:@"ver"]; |
| 363 | } | 363 | } |
| 364 | if (!isUUID) { | 364 | if (!isUUID) { |
| 365 | - [muDic setObject:[CNLiveBusinessTools uuid] forKey:@"uuid"]; | 365 | + [muDic setObject:[CNLiveNetBusinessTools uuid] forKey:@"uuid"]; |
| 366 | } | 366 | } |
| 367 | if (!isLoginId) { | 367 | if (!isLoginId) { |
| 368 | [muDic setObject:CNUserShareModel.uid.length == 0 ? @"" : CNUserShareModel.uid forKey:@"loginSid"]; | 368 | [muDic setObject:CNUserShareModel.uid.length == 0 ? @"" : CNUserShareModel.uid forKey:@"loginSid"]; |
| 1 | +// | ||
| 2 | +// CNLiveEmotionHelper.h | ||
| 3 | +// CNLiveNetAdd | ||
| 4 | +// | ||
| 5 | +// Created by 殷巧娟 on 2019/10/14. | ||
| 6 | +// Copyright © 2019 cnlive. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import <Foundation/Foundation.h> | ||
| 10 | + | ||
| 11 | +NS_ASSUME_NONNULL_BEGIN | ||
| 12 | + | ||
| 13 | +@interface CNLiveEmotionHelper : NSObject | ||
| 14 | ++ (instancetype)sharedInstance; | ||
| 15 | +@end | ||
| 16 | + | ||
| 17 | +@interface CNLiveEmotionHelper (Bundle) | ||
| 18 | ++ (nullable NSBundle *)emotionResourcesBundle; | ||
| 19 | ++ (nullable UIImage *)emotionImageWithName:(nullable NSString *)name; | ||
| 20 | + | ||
| 21 | ++ (nullable NSBundle *)emotionResourcesBundleWithName:(nullable NSString *)bundleName; | ||
| 22 | ++ (nullable UIImage *)emotionImageInBundle:(nullable NSBundle *)bundle withName:(nullable NSString *)name; | ||
| 23 | +@end | ||
| 24 | +NS_ASSUME_NONNULL_END |
| 1 | +// | ||
| 2 | +// CNLiveEmotionHelper.m | ||
| 3 | +// CNLiveNetAdd | ||
| 4 | +// | ||
| 5 | +// Created by 殷巧娟 on 2019/10/14. | ||
| 6 | +// Copyright © 2019 cnlive. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import "CNLiveEmotionHelper.h" | ||
| 10 | + | ||
| 11 | +@implementation CNLiveEmotionHelper | ||
| 12 | ++ (instancetype) sharedInstance { | ||
| 13 | + static dispatch_once_t onceToken; | ||
| 14 | + static CNLiveEmotionHelper *instance = nil; | ||
| 15 | + dispatch_once(&onceToken, ^{ | ||
| 16 | + instance = [[super allocWithZone:NULL] init]; | ||
| 17 | + }); | ||
| 18 | + return instance; | ||
| 19 | +} | ||
| 20 | ++ (id)allocWithZone:(struct _NSZone *)zone { | ||
| 21 | + return [self sharedInstance]; | ||
| 22 | +} | ||
| 23 | +@end | ||
| 24 | +NSString *const QMUIResourcesBundleName = @"QMUIResources.bundle"; | ||
| 25 | +@implementation CNLiveEmotionHelper (Bundle) | ||
| 26 | + | ||
| 27 | ++ (NSBundle *)emotionResourcesBundle { | ||
| 28 | + return [CNLiveEmotionHelper emotionResourcesBundleWithName:QMUIResourcesBundleName]; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | ++ (NSBundle *)emotionResourcesBundleWithName:(NSString *)bundleName { | ||
| 32 | + NSBundle *targetBundle; | ||
| 33 | + NSBundle *mainBundle = [NSBundle bundleWithPath: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:bundleName]]; | ||
| 34 | + targetBundle = mainBundle; | ||
| 35 | + if (!mainBundle) { | ||
| 36 | + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; | ||
| 37 | + NSString *selfString = @"CNLiveBusinessTools.bundle"; | ||
| 38 | + NSDictionary *bundleData = [self parseBundleName:bundleName]; | ||
| 39 | + NSString *name = [bundleData objectForKey:@"name"]; | ||
| 40 | + NSString *type = [bundleData objectForKey:@"type"]; | ||
| 41 | + NSString *bundleUrl = [selfString stringByAppendingPathComponent:name]; | ||
| 42 | + NSURL *url = [bundle URLForResource:bundleUrl withExtension:type]; | ||
| 43 | + targetBundle = [NSBundle bundleWithURL:url]; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | +// NSURL *url = [bundle URLForResource:@"CNLiveBusinessTools.bundle/CNLive_QQEmotion" withExtension:@"bundle"]; | ||
| 47 | +// NSBundle *targetBundle = [NSBundle bundleWithURL:url]; | ||
| 48 | + return targetBundle; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | ++ (UIImage *)emotionImageWithName:(NSString *)name { | ||
| 52 | + NSBundle *bundle = [CNLiveEmotionHelper emotionResourcesBundle]; | ||
| 53 | + return [CNLiveEmotionHelper emotionImageInBundle:bundle withName:name]; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | ++ (UIImage *)emotionImageInBundle:(NSBundle *)bundle withName:(NSString *)name { | ||
| 57 | + if (bundle && name) { | ||
| 58 | + if ([UIImage respondsToSelector:@selector(imageNamed:inBundle:compatibleWithTraitCollection:)]) { | ||
| 59 | + return [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil]; | ||
| 60 | + } else { | ||
| 61 | + NSString *imagePath = [[bundle resourcePath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", name]]; | ||
| 62 | + return [UIImage imageWithContentsOfFile:imagePath]; | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + return nil; | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | ++ (NSDictionary *)parseBundleName:(NSString *)bundleName { | ||
| 69 | + NSArray *bundleData = [bundleName componentsSeparatedByString:@"."]; | ||
| 70 | + if (bundleData.count == 2) { | ||
| 71 | + return @{@"name":bundleData[0], @"type":bundleData[1]}; | ||
| 72 | + } | ||
| 73 | + return nil; | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +@end |
| 1 | +// | ||
| 2 | +// CNLiveQQEmotionManager.h | ||
| 3 | +// testIM | ||
| 4 | +// | ||
| 5 | +// Created by 张旭 on 2018/10/31. | ||
| 6 | +// Copyright © 2018 cnlive. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import <Foundation/Foundation.h> | ||
| 10 | +#import <UIKit/UIKit.h> | ||
| 11 | +#import <QMUIKit/QMUIKit.h> | ||
| 12 | +NS_ASSUME_NONNULL_BEGIN | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 提供一个QQ表情面板,能为绑定的`UITextField`或`UITextView`提供表情的相关功能,包括点击表情输入对应的表情名字、点击删除按钮删除表情。由于表情的插入、删除都会受当前输入框的光标所在位置的影响,所以请在适当的时机更新`selectedRangeForBoundTextInput`的值,具体情况请查看属性的注释。 | ||
| 18 | + * @warning 由于QQ表情图片较多(文件大小约400K),因此表情图片被以bundle的形式存放在 | ||
| 19 | + * @warning 一个`CNLiveQQEmotionManager`无法同时绑定`boundTextField`和`boundTextView`,在两者都绑定的情况下,优先使用`boundTextField`。 | ||
| 20 | + * @warning 由于`CNLiveQQEmotionManager`里面多个地方会调用`boundTextView.text`,而`setText:`并不会触发`UITextViewDelegate`的`textViewDidChange:`或`UITextViewTextDidChangeNotification`,从而在刷新表情面板里的发送按钮的enabled状态时可能不及时,所以`CNLiveQQEmotionManager`要求绑定的`QMUITextView`必须打开`shouldResponseToProgrammaticallyTextChanges`属性 | ||
| 21 | + */ | ||
| 22 | +@interface CNLiveQQEmotionManager : NSObject | ||
| 23 | + | ||
| 24 | +/// 要绑定的UITextField | ||
| 25 | +@property(nonatomic, weak) UITextField *boundTextField; | ||
| 26 | + | ||
| 27 | +/// 要绑定的UITextView | ||
| 28 | +@property(nonatomic, weak) UITextView *boundTextView; | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * `selectedRangeForBoundTextInput`决定了表情将会被插入(删除)的位置,因此使用控件的时候需要及时更新它。 | ||
| 32 | + * | ||
| 33 | + * 通常用到的更新时机包括: | ||
| 34 | + * - 降下键盘显示QQ表情面板之前(调用resignFirstResponder、endEditing:之前) | ||
| 35 | + * - <UITextViewDelegate>的`textViewDidChangeSelection:`回调里 | ||
| 36 | + * - 输入框里的文字发生变化时,例如点了发送按钮后输入框文字会被清空,此时要重置`selectedRangeForBoundTextInput`为0 | ||
| 37 | + */ | ||
| 38 | +@property(nonatomic, assign) NSRange selectedRangeForBoundTextInput; | ||
| 39 | + | ||
| 40 | +/** | ||
| 41 | + * 显示QQ表情的表情面板,已被设置了默认的`didSelectEmotionBlock`和`didSelectDeleteButtonBlock`,在`CNLiveQQEmotionManager`初始化完后,即可将`emotionView`添加到界面上。 | ||
| 42 | + */ | ||
| 43 | +@property(nonatomic, strong, readonly) QMUIEmotionView *emotionView; | ||
| 44 | + | ||
| 45 | +/** | ||
| 46 | + * 将当前光标所在位置的表情删除,在调用前请注意更新`selectedRangeForBoundTextInput` | ||
| 47 | + * @param forceDelete 当没有删除掉表情的情况下(可能光标前面并不是一个表情字符),要不要强制删掉光标前的字符。YES表示强制删掉,NO表示不删,交给系统键盘处理 | ||
| 48 | + * @return 表示是否成功删除了文字(如果并不是删除表情,而是删除普通字符,也是返回YES) | ||
| 49 | + */ | ||
| 50 | +- (BOOL)deleteEmotionDisplayNameAtCurrentSelectedRangeForce:(BOOL)forceDelete; | ||
| 51 | + | ||
| 52 | +/** | ||
| 53 | + * 在 `UITextViewDelegate` 的 `textView:shouldChangeTextInRange:replacementText:` 或者 `QMUITextFieldDelegate` 的 `textField:shouldChangeTextInRange:replacementText:` 方法里调用,根据返回值来决定是否应该调用 `deleteEmotionDisplayNameAtCurrentSelectedRangeForce:` | ||
| 54 | + | ||
| 55 | + @param range 要发生变化的文字所在的range | ||
| 56 | + @param text 要被替换为的文字 | ||
| 57 | + | ||
| 58 | + @return 是否会接管键盘的删除按钮事件,`YES` 表示接管,可调用 `deleteEmotionDisplayNameAtCurrentSelectedRangeForce:` 方法,`NO` 表示不可接管,应该使用系统自身的删除事件响应。 | ||
| 59 | + */ | ||
| 60 | +- (BOOL)shouldTakeOverControlDeleteKeyWithChangeTextInRange:(NSRange)range replacementText:(NSString *)text; | ||
| 61 | + | ||
| 62 | +/** | ||
| 63 | + * QQ表情的数组,会做缓存,图片只会加载一次 | ||
| 64 | + */ | ||
| 65 | ++ (NSArray<QMUIEmotion *> *)emotionsForQQ; | ||
| 66 | + | ||
| 67 | +@end | ||
| 68 | + | ||
| 69 | +NS_ASSUME_NONNULL_END |
| 1 | +// | ||
| 2 | +// CNLiveQQEmotionManager.m | ||
| 3 | +// testIM | ||
| 4 | +// | ||
| 5 | +// Created by 张旭 on 2018/10/31. | ||
| 6 | +// Copyright © 2018 cnlive. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import "CNLiveQQEmotionManager.h" | ||
| 10 | +#import "QMUIEmotion+CNLiveEmotion.h" | ||
| 11 | +#import "CNLiveEmotionHelper.h" | ||
| 12 | +/** | ||
| 13 | + * 加载Emoji图片资源失败标识 | ||
| 14 | + */ | ||
| 15 | +BOOL isLoadEmojiFailed; | ||
| 16 | +BOOL isLoadingEmoji;//是否正在加载emoji | ||
| 17 | +long CNLiveEmojiLoadFailCount = 0; | ||
| 18 | +NSString *const QQEmotionString = @"0-[微笑];1-[撇嘴];2-[色];3-[发呆];4-[得意];5-[流泪];6-[害羞];7-[闭嘴];8-[睡];9-[大哭];10-[尴尬];11-[发怒];12-[调皮];13-[呲牙];14-[惊讶];15-[难过];16-[酷];17-[冷汗];18-[抓狂];19-[吐];20-[偷笑];21-[可爱];22-[白眼];23-[傲慢];24-[饥饿];25-[困];26-[惊恐];27-[流汗];28-[憨笑];29-[大兵];30-[奋斗];31-[咒骂];32-[疑问];33-[嘘];34-[晕];35-[折磨];36-[衰];37-[骷髅];38-[敲打];39-[再见];40-[擦汗];41-[抠鼻];42-[鼓掌];43-[糗大了];44-[坏笑];45-[左哼哼];46-[右哼哼];47-[哈欠];48-[鄙视];49-[委屈];50-[快哭了];51-[阴险];52-[亲亲];53-[吓];54-[可怜];55-[菜刀];56-[西瓜];57-[啤酒];58-[篮球];59-[乒乓];60-[咖啡];61-[饭];62-[猪头];63-[玫瑰];64-[凋谢];65-[示爱];66-[爱心];67-[心碎];68-[蛋糕];69-[闪电];70-[炸弹];71-[刀];72-[足球];73-[瓢虫];74-[便便];75-[月亮];76-[太阳];77-[礼物];78-[拥抱];79-[强];80-[弱];81-[握手];82-[胜利];83-[抱拳];84-[勾引];85-[拳头];86-[差劲];87-[爱你];88-[NO];89-[OK];90-[爱情];91-[飞吻];92-[跳跳];93-[发抖];94-[怄火];95-[转圈];96-[磕头];97-[回头];98-[跳绳];99-[挥手];100-[激动];101-[街舞];102-[献吻];103-[左太极];104-[右太极];105-[嘿哈];106-[捂脸];107-[奸笑];108-[机智];109-[皱眉];110-[耶];111-[红包];112-[鸡];113-[生病];114-[震惊];115-[金钱];116-[懵圈];117-[大眼];118-[保密];119-[宝宝];120-[装死];121-[666];122-[笑哭];123-[热];124-[比心];125-[送口红];126-[矿泉水]"; | ||
| 19 | + | ||
| 20 | +static NSArray<QMUIEmotion *> *QQEmotionArray; | ||
| 21 | + | ||
| 22 | +@protocol CNLiveQQEmotionInputViewProtocol <UITextInput> | ||
| 23 | + | ||
| 24 | +@property(nonatomic, copy) NSString *text; | ||
| 25 | +@property(nonatomic, assign, readonly) NSRange selectedRange; | ||
| 26 | +@end | ||
| 27 | + | ||
| 28 | +@implementation CNLiveQQEmotionManager | ||
| 29 | + | ||
| 30 | +- (instancetype)init { | ||
| 31 | + self = [super init]; | ||
| 32 | + if (self) { | ||
| 33 | + _emotionView = [[QMUIEmotionView alloc] init]; | ||
| 34 | + self.emotionView.emotions = [CNLiveQQEmotionManager emotionsForQQ]; | ||
| 35 | + __weak CNLiveQQEmotionManager *weakSelf = self; | ||
| 36 | + self.emotionView.didSelectEmotionBlock = ^(NSInteger index, QMUIEmotion *emotion) { | ||
| 37 | + if (!weakSelf.boundInputView) return; | ||
| 38 | + | ||
| 39 | + NSString *inputText = weakSelf.boundInputView.text; | ||
| 40 | + // 用一个局部变量先保存selectedRangeForBoundTextInput的值,是为了避免在接下来这段代码执行的过程中,外部可能修改了self.selectedRangeForBoundTextInput的值,导致计算错误 | ||
| 41 | + NSRange selectedRange = weakSelf.selectedRangeForBoundTextInput; | ||
| 42 | + if (selectedRange.location <= inputText.length) { | ||
| 43 | + // 在输入框文字的中间插入表情 | ||
| 44 | + NSMutableString *mutableText = [NSMutableString stringWithString:inputText ?: @""]; | ||
| 45 | + [mutableText insertString:emotion.displayName atIndex:selectedRange.location]; | ||
| 46 | + weakSelf.boundInputView.text = mutableText;// UITextView setText:会触发textViewDidChangeSelection:,而如果在这个delegate里更新self.selectedRangeForBoundTextInput,就会导致计算错误 | ||
| 47 | + selectedRange = NSMakeRange(selectedRange.location + emotion.displayName.length, 0); | ||
| 48 | + } else { | ||
| 49 | + // 在输入框文字的结尾插入表情 | ||
| 50 | + inputText = [inputText stringByAppendingString:emotion.displayName]; | ||
| 51 | + weakSelf.boundInputView.text = inputText; | ||
| 52 | + selectedRange = NSMakeRange(weakSelf.boundInputView.text.length, 0);// 始终都应该从 boundInputView.text 获取最终的文字,因为可能在 setText: 时受 maximumTextLength 的限制导致文字截断 | ||
| 53 | + } | ||
| 54 | + weakSelf.selectedRangeForBoundTextInput = selectedRange; | ||
| 55 | + }; | ||
| 56 | + self.emotionView.didSelectDeleteButtonBlock = ^{ | ||
| 57 | + [weakSelf deleteEmotionDisplayNameAtCurrentSelectedRangeForce:YES]; | ||
| 58 | + }; | ||
| 59 | + } | ||
| 60 | + return self; | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +- (UIView<CNLiveQQEmotionInputViewProtocol> *)boundInputView { | ||
| 64 | + if (self.boundTextField) { | ||
| 65 | + return (UIView<CNLiveQQEmotionInputViewProtocol> *)self.boundTextField; | ||
| 66 | + } else if (self.boundTextView) { | ||
| 67 | + return (UIView<CNLiveQQEmotionInputViewProtocol> *)self.boundTextView; | ||
| 68 | + } | ||
| 69 | + return nil; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +- (BOOL)deleteEmotionDisplayNameAtCurrentSelectedRangeForce:(BOOL)forceDelete { | ||
| 73 | + if (!self.boundInputView) return NO; | ||
| 74 | + | ||
| 75 | + NSRange selectedRange = self.selectedRangeForBoundTextInput; | ||
| 76 | + NSString *text = self.boundInputView.text; | ||
| 77 | + | ||
| 78 | + // 没有文字或者光标位置前面没文字 | ||
| 79 | + if (!text.length || NSMaxRange(selectedRange) == 0) { | ||
| 80 | + return NO; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + BOOL hasDeleteEmotionDisplayNameSuccess = NO; | ||
| 84 | + NSInteger emotionDisplayNameMinimumLength = 3;// QQ表情里的最短displayName的长度 | ||
| 85 | + NSInteger lengthForStringBeforeSelectedRange = selectedRange.location; | ||
| 86 | + NSString *lastCharacterBeforeSelectedRange = [text substringWithRange:NSMakeRange(selectedRange.location - 1, 1)]; | ||
| 87 | + if ([lastCharacterBeforeSelectedRange isEqualToString:@"]"] && lengthForStringBeforeSelectedRange >= emotionDisplayNameMinimumLength) { | ||
| 88 | + NSInteger beginIndex = lengthForStringBeforeSelectedRange - (emotionDisplayNameMinimumLength - 1);// 从"]"之前的第n个字符开始查找 | ||
| 89 | + NSInteger endIndex = MAX(0, lengthForStringBeforeSelectedRange - 5);// 直到"]"之前的第n个字符结束查找,这里写5只是简单的限定,这个数字只要比所有QQ表情的displayName长度长就行了 | ||
| 90 | + for (NSInteger i = beginIndex; i >= endIndex; i --) { | ||
| 91 | + NSString *checkingCharacter = [text substringWithRange:NSMakeRange(i, 1)]; | ||
| 92 | + if ([checkingCharacter isEqualToString:@"]"]) { | ||
| 93 | + // 查找过程中还没遇到"["就已经遇到"]"了,说明是非法的表情字符串,所以直接终止 | ||
| 94 | + break; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + if ([checkingCharacter isEqualToString:@"["]) { | ||
| 98 | + NSRange deletingDisplayNameRange = NSMakeRange(i, lengthForStringBeforeSelectedRange - i); | ||
| 99 | + self.boundInputView.text = [text stringByReplacingCharactersInRange:deletingDisplayNameRange withString:@""]; | ||
| 100 | + self.selectedRangeForBoundTextInput = NSMakeRange(deletingDisplayNameRange.location, 0); | ||
| 101 | + hasDeleteEmotionDisplayNameSuccess = YES; | ||
| 102 | + break; | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + if (hasDeleteEmotionDisplayNameSuccess) { | ||
| 108 | + return YES; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + if (forceDelete) { | ||
| 112 | + if (NSMaxRange(selectedRange) <= text.length) { | ||
| 113 | + if (selectedRange.length > 0) { | ||
| 114 | + // 如果选中区域是一段文字,则删掉这段文字 | ||
| 115 | + self.boundInputView.text = [text stringByReplacingCharactersInRange:selectedRange withString:@""]; | ||
| 116 | + self.selectedRangeForBoundTextInput = NSMakeRange(selectedRange.location, 0); | ||
| 117 | + } else if (selectedRange.location > 0) { | ||
| 118 | + // 如果并没有选中一段文字,则删掉光标前一个字符 | ||
| 119 | + NSString *textAfterDelete = [text qmui_stringByRemoveCharacterAtIndex:selectedRange.location - 1]; | ||
| 120 | + self.boundInputView.text = textAfterDelete; | ||
| 121 | + self.selectedRangeForBoundTextInput = NSMakeRange(selectedRange.location - (text.length - textAfterDelete.length), 0); | ||
| 122 | + } | ||
| 123 | + } else { | ||
| 124 | + // 选中区域超过文字长度了,非法数据,则直接删掉最后一个字符 | ||
| 125 | + self.boundInputView.text = [text qmui_stringByRemoveLastCharacter]; | ||
| 126 | + self.selectedRangeForBoundTextInput = NSMakeRange(self.boundInputView.text.length, 0); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + return YES; | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + return NO; | ||
| 133 | +} | ||
| 134 | + | ||
| 135 | +- (BOOL)shouldTakeOverControlDeleteKeyWithChangeTextInRange:(NSRange)range replacementText:(NSString *)text { | ||
| 136 | + BOOL isDeleteKeyPressed = text.length == 0 && self.boundInputView.text.length - 1 == range.location; | ||
| 137 | + BOOL hasMarkedText = !!self.boundInputView.markedTextRange; | ||
| 138 | + return isDeleteKeyPressed && !hasMarkedText; | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | ++ (UIImage *)imageForQQEmotionWithIdentifier:(NSString *)identifier { | ||
| 142 | + return [CNLiveEmotionHelper emotionImageInBundle:[CNLiveEmotionHelper emotionResourcesBundleWithName:CNLiveResourcesQQEmotionBundleName] withName:identifier]; | ||
| 143 | +} | ||
| 144 | + | ||
| 145 | ++ (NSArray<QMUIEmotion *> *)emotionsForQQ { | ||
| 146 | + if (QQEmotionArray) { | ||
| 147 | + if (!isLoadEmojiFailed) | ||
| 148 | + {//全部加载成功 | ||
| 149 | + return QQEmotionArray; | ||
| 150 | + }else | ||
| 151 | + {//有图片加载失败 | ||
| 152 | + NSMutableArray<QMUIEmotion *> *emotionsTemp = [NSMutableArray arrayWithArray:QQEmotionArray]; | ||
| 153 | + if(!isLoadingEmoji) | ||
| 154 | + { | ||
| 155 | + [self asyncLoadImages:emotionsTemp]; | ||
| 156 | + } | ||
| 157 | + return QQEmotionArray; | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + NSMutableArray<QMUIEmotion *> *emotions = [[NSMutableArray alloc] init]; | ||
| 162 | + NSArray<NSString *> *emotionStringArray = [QQEmotionString componentsSeparatedByString:@";"]; | ||
| 163 | + for (NSString *emotionString in emotionStringArray) { | ||
| 164 | + NSArray<NSString *> *emotionItem = [emotionString componentsSeparatedByString:@"-"]; | ||
| 165 | + NSString *identifier = [NSString stringWithFormat:@"smiley_%@", emotionItem.firstObject]; | ||
| 166 | + QMUIEmotion *emotion = [QMUIEmotion emotionWithIdentifier:identifier displayName:emotionItem.lastObject]; | ||
| 167 | + [emotions addObject:emotion]; | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + QQEmotionArray = [NSArray arrayWithArray:emotions]; | ||
| 171 | + [self asyncLoadImages:emotions]; | ||
| 172 | + return QQEmotionArray; | ||
| 173 | +} | ||
| 174 | + | ||
| 175 | +// 在子线程预加载 zx | ||
| 176 | ++ (void)asyncLoadImages:(NSArray<QMUIEmotion *> *)emotions{ | ||
| 177 | + isLoadingEmoji = YES; | ||
| 178 | + dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
| 179 | + for (QMUIEmotion *e in emotions) { | ||
| 180 | + if (e.image == nil) { | ||
| 181 | + UIImage *image = [QMUIEmotion cnliveImageWithEmotion:e]; | ||
| 182 | + if (image == nil) { | ||
| 183 | + NSLog(@"加载emoji失败id:%@",e.identifier); | ||
| 184 | + isLoadEmojiFailed = YES; | ||
| 185 | + }else | ||
| 186 | + { | ||
| 187 | + e.image = image; | ||
| 188 | + isLoadEmojiFailed = NO; | ||
| 189 | + } | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + isLoadingEmoji = NO; | ||
| 193 | + }); | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | + | ||
| 197 | +@end |
| 1 | +// | ||
| 2 | +// QMUIEmotion+CNLiveEmotion.h | ||
| 3 | +// CNLiveNetAdd | ||
| 4 | +// | ||
| 5 | +// Created by 张旭 on 2018/11/3. | ||
| 6 | +// Copyright © 2018 cnlive. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import <QMUIKit/QMUIKit.h> | ||
| 10 | + | ||
| 11 | +NS_ASSUME_NONNULL_BEGIN | ||
| 12 | + | ||
| 13 | +#define CNLiveResourcesQQEmotionBundleName @"CNLive_QQEmotion.bundle" | ||
| 14 | + | ||
| 15 | +@interface QMUIEmotion (CNLiveEmotion) | ||
| 16 | + | ||
| 17 | ++ (UIImage *)cnliveImageWithEmotion:(QMUIEmotion *)emotion; | ||
| 18 | + | ||
| 19 | +@end | ||
| 20 | + | ||
| 21 | +NS_ASSUME_NONNULL_END |
| 1 | +// | ||
| 2 | +// QMUIEmotion+CNLiveEmotion.m | ||
| 3 | +// CNLiveNetAdd | ||
| 4 | +// | ||
| 5 | +// Created by 张旭 on 2018/11/3. | ||
| 6 | +// Copyright © 2018 cnlive. All rights reserved. | ||
| 7 | +// | ||
| 8 | + | ||
| 9 | +#import "QMUIEmotion+CNLiveEmotion.h" | ||
| 10 | +#import "CNLiveEmotionHelper.h" | ||
| 11 | +@implementation QMUIEmotion (CNLiveEmotion) | ||
| 12 | + | ||
| 13 | ++ (UIImage *)cnliveImageWithEmotion:(QMUIEmotion *)emotion | ||
| 14 | +{ | ||
| 15 | + UIImage *image = [CNLiveEmotionHelper emotionImageInBundle:[CNLiveEmotionHelper emotionResourcesBundleWithName:CNLiveResourcesQQEmotionBundleName] withName:emotion.identifier]; | ||
| 16 | + return image; | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +@end |
| @@ -356,6 +356,7 @@ | @@ -356,6 +356,7 @@ | ||
| 356 | "${BUILT_PRODUCTS_DIR}/CNLiveTripartiteManagement/CNLiveTripartiteManagement.framework", | 356 | "${BUILT_PRODUCTS_DIR}/CNLiveTripartiteManagement/CNLiveTripartiteManagement.framework", |
| 357 | "${BUILT_PRODUCTS_DIR}/CNLiveUserManagement/CNLiveUserManagement.framework", | 357 | "${BUILT_PRODUCTS_DIR}/CNLiveUserManagement/CNLiveUserManagement.framework", |
| 358 | "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework", | 358 | "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework", |
| 359 | + "${BUILT_PRODUCTS_DIR}/QMUIKit/QMUIKit.framework", | ||
| 359 | ); | 360 | ); |
| 360 | name = "[CP] Embed Pods Frameworks"; | 361 | name = "[CP] Embed Pods Frameworks"; |
| 361 | outputPaths = ( | 362 | outputPaths = ( |
| @@ -367,6 +368,7 @@ | @@ -367,6 +368,7 @@ | ||
| 367 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveTripartiteManagement.framework", | 368 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveTripartiteManagement.framework", |
| 368 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveUserManagement.framework", | 369 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveUserManagement.framework", |
| 369 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework", | 370 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework", |
| 371 | + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/QMUIKit.framework", | ||
| 370 | ); | 372 | ); |
| 371 | runOnlyForDeploymentPostprocessing = 0; | 373 | runOnlyForDeploymentPostprocessing = 0; |
| 372 | shellPath = /bin/sh; | 374 | shellPath = /bin/sh; |
| @@ -7,12 +7,14 @@ | @@ -7,12 +7,14 @@ | ||
| 7 | // | 7 | // |
| 8 | 8 | ||
| 9 | #import "CNLiveAppDelegate.h" | 9 | #import "CNLiveAppDelegate.h" |
| 10 | +#import "CNLiveQQEmotionManager.h" | ||
| 10 | 11 | ||
| 11 | @implementation CNLiveAppDelegate | 12 | @implementation CNLiveAppDelegate |
| 12 | 13 | ||
| 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions |
| 14 | { | 15 | { |
| 15 | // Override point for customization after application launch. | 16 | // Override point for customization after application launch. |
| 17 | + [CNLiveQQEmotionManager emotionsForQQ]; | ||
| 16 | return YES; | 18 | return YES; |
| 17 | } | 19 | } |
| 18 | 20 |
| @@ -12,6 +12,7 @@ target 'CNLiveBusinessTools_Example' do | @@ -12,6 +12,7 @@ target 'CNLiveBusinessTools_Example' do | ||
| 12 | pod 'CNLiveUserManagement' | 12 | pod 'CNLiveUserManagement' |
| 13 | pod 'CNLiveBaseKit' | 13 | pod 'CNLiveBaseKit' |
| 14 | pod 'CNLiveRequestBastKit' | 14 | pod 'CNLiveRequestBastKit' |
| 15 | + pod 'CNLiveTripartiteManagement/QMUIKit' | ||
| 15 | 16 | ||
| 16 | target 'CNLiveBusinessTools_Tests' do | 17 | target 'CNLiveBusinessTools_Tests' do |
| 17 | inherit! :search_paths | 18 | inherit! :search_paths |