- 充值页面
- 充值页面返回挽留弹窗 - 圈子一级页面接口数据接入 - openIM sdk 接入 - IM 会话列表
This commit is contained in:
parent
c0df6013fc
commit
a2e352aaf0
Binary file not shown.
|
After Width: | Height: | Size: 220 KiB |
3
Podfile
3
Podfile
|
|
@ -43,7 +43,8 @@ target 'QuickLocation' do
|
||||||
|
|
||||||
#第三方SDk
|
#第三方SDk
|
||||||
pod 'GYSDK' #个推一键登录
|
pod 'GYSDK' #个推一键登录
|
||||||
|
pod 'OpenIMSDK' #OpenIM
|
||||||
|
|
||||||
#高德地图
|
#高德地图
|
||||||
pod 'AMap3DMap' #3D地图SDK
|
pod 'AMap3DMap' #3D地图SDK
|
||||||
pod 'AMapSearch' #地图SDK搜索功能
|
pod 'AMapSearch' #地图SDK搜索功能
|
||||||
|
|
|
||||||
41
Podfile.lock
41
Podfile.lock
|
|
@ -82,12 +82,44 @@ PODS:
|
||||||
- MarqueeLabel (4.5.3)
|
- MarqueeLabel (4.5.3)
|
||||||
- Masonry (1.1.0)
|
- Masonry (1.1.0)
|
||||||
- MBProgressHUD (1.2.0)
|
- MBProgressHUD (1.2.0)
|
||||||
|
- MJExtension (3.4.2)
|
||||||
- MJRefresh (3.7.9)
|
- MJRefresh (3.7.9)
|
||||||
- Moya (15.0.0):
|
- Moya (15.0.0):
|
||||||
- Moya/Core (= 15.0.0)
|
- Moya/Core (= 15.0.0)
|
||||||
- Moya/Core (15.0.0):
|
- Moya/Core (15.0.0):
|
||||||
- Alamofire (~> 5.0)
|
- Alamofire (~> 5.0)
|
||||||
- ObjectMapper (4.4.2)
|
- ObjectMapper (4.4.2)
|
||||||
|
- "OpenIMSDK (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- "OpenIMSDK/Callbacker (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/CallbackProxy (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/Interface (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/Model (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/Utils (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Callbacker (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Model
|
||||||
|
- OpenIMSDK/Utils
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/CallbackProxy (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Utils
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Interface (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Callbacker
|
||||||
|
- OpenIMSDK/CallbackProxy
|
||||||
|
- OpenIMSDK/Model
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Model (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Utils
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Utils (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDKCore (3.8.3+3)"
|
||||||
- Popover (1.3.0)
|
- Popover (1.3.0)
|
||||||
- RxCocoa (6.8.0):
|
- RxCocoa (6.8.0):
|
||||||
- RxRelay (= 6.8.0)
|
- RxRelay (= 6.8.0)
|
||||||
|
|
@ -138,6 +170,7 @@ DEPENDENCIES:
|
||||||
- MJRefresh
|
- MJRefresh
|
||||||
- Moya
|
- Moya
|
||||||
- ObjectMapper
|
- ObjectMapper
|
||||||
|
- OpenIMSDK
|
||||||
- Popover
|
- Popover
|
||||||
- RxCocoa
|
- RxCocoa
|
||||||
- RxDataSources
|
- RxDataSources
|
||||||
|
|
@ -179,9 +212,12 @@ SPEC REPOS:
|
||||||
- lottie-ios
|
- lottie-ios
|
||||||
- MarqueeLabel
|
- MarqueeLabel
|
||||||
- Masonry
|
- Masonry
|
||||||
|
- MJExtension
|
||||||
- MJRefresh
|
- MJRefresh
|
||||||
- Moya
|
- Moya
|
||||||
- ObjectMapper
|
- ObjectMapper
|
||||||
|
- OpenIMSDK
|
||||||
|
- OpenIMSDKCore
|
||||||
- Popover
|
- Popover
|
||||||
- RxCocoa
|
- RxCocoa
|
||||||
- RxDataSources
|
- RxDataSources
|
||||||
|
|
@ -235,9 +271,12 @@ SPEC CHECKSUMS:
|
||||||
MarqueeLabel: 0c57d4c6634e04a6d015af79f7c9a175b2309525
|
MarqueeLabel: 0c57d4c6634e04a6d015af79f7c9a175b2309525
|
||||||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||||
MBProgressHUD: 1b0fb447e80a0fda94808180750e8b78a07b3cd2
|
MBProgressHUD: 1b0fb447e80a0fda94808180750e8b78a07b3cd2
|
||||||
|
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||||
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
||||||
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
|
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
|
||||||
|
OpenIMSDK: c1880296ead605bcac2a289ad0aef9170fe6e6df
|
||||||
|
OpenIMSDKCore: 75caba22be8ee484011f367711178312bd64a17d
|
||||||
Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
|
Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
|
||||||
RxCocoa: 2d33c1e1e5d66492052ad46b11024ae287572880
|
RxCocoa: 2d33c1e1e5d66492052ad46b11024ae287572880
|
||||||
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
||||||
|
|
@ -256,6 +295,6 @@ SPEC CHECKSUMS:
|
||||||
URLNavigator: e9c0426ba6e6ac57f34d018bbf3df840797f984d
|
URLNavigator: e9c0426ba6e6ac57f34d018bbf3df840797f984d
|
||||||
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
|
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
|
||||||
|
|
||||||
PODFILE CHECKSUM: 7d3667576e8d6c3f1a98be0e406f215041cf2eb7
|
PODFILE CHECKSUM: d9389fd0d3da8895e9ddac8adbec655edaf9bb3d
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2013-2019 MJExtension (https://github.com/CoderMJLee/MJExtension)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// MJExtension.h
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 14-1-15.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "NSObject+MJCoding.h"
|
||||||
|
#import "NSObject+MJProperty.h"
|
||||||
|
#import "NSObject+MJClass.h"
|
||||||
|
#import "NSObject+MJKeyValue.h"
|
||||||
|
#import "NSString+MJExtension.h"
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
|
||||||
|
//! Project version number for MJExtension.
|
||||||
|
FOUNDATION_EXPORT double MJExtensionVersionNumber;
|
||||||
|
|
||||||
|
//! Project version string for MJExtension.
|
||||||
|
FOUNDATION_EXPORT const unsigned char MJExtensionVersionString[];
|
||||||
|
|
||||||
|
// In this header, you should import all the public headers of your framework using statements like #import <MJExtension/PublicHeader.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
|
||||||
|
#ifndef __MJExtensionConst__H__
|
||||||
|
#define __MJExtensionConst__H__
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#ifndef MJ_LOCK
|
||||||
|
#define MJ_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MJ_UNLOCK
|
||||||
|
#define MJ_UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 信号量
|
||||||
|
#define MJExtensionSemaphoreCreate \
|
||||||
|
extern dispatch_semaphore_t mje_signalSemaphore; \
|
||||||
|
extern dispatch_once_t mje_onceTokenSemaphore; \
|
||||||
|
dispatch_once(&mje_onceTokenSemaphore, ^{ \
|
||||||
|
mje_signalSemaphore = dispatch_semaphore_create(1); \
|
||||||
|
});
|
||||||
|
|
||||||
|
// 过期
|
||||||
|
#define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
|
||||||
|
|
||||||
|
// 构建错误
|
||||||
|
#define MJExtensionBuildError(clazz, msg) \
|
||||||
|
NSError *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; \
|
||||||
|
[clazz setMj_error:error];
|
||||||
|
|
||||||
|
// 日志输出
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define MJExtensionLog(...) NSLog(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define MJExtensionLog(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言
|
||||||
|
* @param condition 条件
|
||||||
|
* @param returnValue 返回值
|
||||||
|
*/
|
||||||
|
#define MJExtensionAssertError(condition, returnValue, clazz, msg) \
|
||||||
|
[clazz setMj_error:nil]; \
|
||||||
|
if ((condition) == NO) { \
|
||||||
|
MJExtensionBuildError(clazz, msg); \
|
||||||
|
return returnValue;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MJExtensionAssert2(condition, returnValue) \
|
||||||
|
if ((condition) == NO) return returnValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言
|
||||||
|
* @param condition 条件
|
||||||
|
*/
|
||||||
|
#define MJExtensionAssert(condition) MJExtensionAssert2(condition, )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言
|
||||||
|
* @param param 参数
|
||||||
|
* @param returnValue 返回值
|
||||||
|
*/
|
||||||
|
#define MJExtensionAssertParamNotNil2(param, returnValue) \
|
||||||
|
MJExtensionAssert2((param) != nil, returnValue)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言
|
||||||
|
* @param param 参数
|
||||||
|
*/
|
||||||
|
#define MJExtensionAssertParamNotNil(param) MJExtensionAssertParamNotNil2(param, )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印所有的属性
|
||||||
|
*/
|
||||||
|
#define MJLogAllIvars \
|
||||||
|
- (NSString *)description \
|
||||||
|
{ \
|
||||||
|
return [self mj_keyValues].description; \
|
||||||
|
}
|
||||||
|
#define MJExtensionLogAllProperties MJLogAllIvars
|
||||||
|
|
||||||
|
/** 仅在 Debugger 展示所有的属性 */
|
||||||
|
#define MJImplementDebugDescription \
|
||||||
|
- (NSString *)debugDescription \
|
||||||
|
{ \
|
||||||
|
return [self mj_keyValues].debugDescription; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型(属性类型)
|
||||||
|
*/
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeInt;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeShort;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeFloat;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeDouble;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeLong;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeLongLong;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeChar;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeBOOL1;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeBOOL2;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypePointer;
|
||||||
|
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeIvar;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeMethod;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeBlock;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeClass;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeSEL;
|
||||||
|
FOUNDATION_EXPORT NSString *const MJPropertyTypeId;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __MJExtensionConst__M__
|
||||||
|
#define __MJExtensionConst__M__
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成员变量类型(属性类型)
|
||||||
|
*/
|
||||||
|
NSString *const MJPropertyTypeInt = @"i";
|
||||||
|
NSString *const MJPropertyTypeShort = @"s";
|
||||||
|
NSString *const MJPropertyTypeFloat = @"f";
|
||||||
|
NSString *const MJPropertyTypeDouble = @"d";
|
||||||
|
NSString *const MJPropertyTypeLong = @"l";
|
||||||
|
NSString *const MJPropertyTypeLongLong = @"q";
|
||||||
|
NSString *const MJPropertyTypeChar = @"c";
|
||||||
|
NSString *const MJPropertyTypeBOOL1 = @"c";
|
||||||
|
NSString *const MJPropertyTypeBOOL2 = @"b";
|
||||||
|
NSString *const MJPropertyTypePointer = @"*";
|
||||||
|
|
||||||
|
NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}";
|
||||||
|
NSString *const MJPropertyTypeMethod = @"^{objc_method=}";
|
||||||
|
NSString *const MJPropertyTypeBlock = @"@?";
|
||||||
|
NSString *const MJPropertyTypeClass = @"#";
|
||||||
|
NSString *const MJPropertyTypeSEL = @":";
|
||||||
|
NSString *const MJPropertyTypeId = @"@";
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// MJFoundation.h
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 14/7/16.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface MJFoundation : NSObject
|
||||||
|
|
||||||
|
+ (BOOL)isClassFromFoundation:(Class)c;
|
||||||
|
+ (BOOL)isFromNSObjectProtocolProperty:(NSString *)propertyName;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// MJFoundation.m
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 14/7/16.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
#import <CoreData/CoreData.h>
|
||||||
|
#import "objc/runtime.h"
|
||||||
|
|
||||||
|
@implementation MJFoundation
|
||||||
|
|
||||||
|
+ (BOOL)isClassFromFoundation:(Class)c
|
||||||
|
{
|
||||||
|
if (c == [NSObject class] || c == [NSManagedObject class]) return YES;
|
||||||
|
|
||||||
|
static NSSet *foundationClasses;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
// 集合中没有NSObject,因为几乎所有的类都是继承自NSObject,具体是不是NSObject需要特殊判断
|
||||||
|
foundationClasses = [NSSet setWithObjects:
|
||||||
|
[NSURL class],
|
||||||
|
[NSDate class],
|
||||||
|
[NSValue class],
|
||||||
|
[NSData class],
|
||||||
|
[NSError class],
|
||||||
|
[NSArray class],
|
||||||
|
[NSDictionary class],
|
||||||
|
[NSString class],
|
||||||
|
[NSAttributedString class], nil];
|
||||||
|
});
|
||||||
|
|
||||||
|
__block BOOL result = NO;
|
||||||
|
[foundationClasses enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) {
|
||||||
|
if ([c isSubclassOfClass:foundationClass]) {
|
||||||
|
result = YES;
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)isFromNSObjectProtocolProperty:(NSString *)propertyName
|
||||||
|
{
|
||||||
|
if (!propertyName) return NO;
|
||||||
|
|
||||||
|
static NSSet<NSString *> *objectProtocolPropertyNames;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
unsigned int count = 0;
|
||||||
|
objc_property_t *propertyList = protocol_copyPropertyList(@protocol(NSObject), &count);
|
||||||
|
NSMutableSet *propertyNames = [NSMutableSet setWithCapacity:count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
objc_property_t property = propertyList[i];
|
||||||
|
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
|
||||||
|
if (propertyName) {
|
||||||
|
[propertyNames addObject:propertyName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objectProtocolPropertyNames = [propertyNames copy];
|
||||||
|
free(propertyList);
|
||||||
|
});
|
||||||
|
|
||||||
|
return [objectProtocolPropertyNames containsObject:propertyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// MJProperty.h
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/4/17.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
// 包装一个成员属性
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import "MJPropertyType.h"
|
||||||
|
#import "MJPropertyKey.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包装一个成员
|
||||||
|
*/
|
||||||
|
@interface MJProperty : NSObject
|
||||||
|
/** 成员属性 */
|
||||||
|
@property (nonatomic, assign) objc_property_t property;
|
||||||
|
/** 成员属性的名字 */
|
||||||
|
@property (nonatomic, readonly) NSString *name;
|
||||||
|
|
||||||
|
/** 成员属性的类型 */
|
||||||
|
@property (nonatomic, readonly) MJPropertyType *type;
|
||||||
|
/** 成员属性来源于哪个类(可能是父类) */
|
||||||
|
@property (nonatomic, assign) Class srcClass;
|
||||||
|
|
||||||
|
/**** 同一个成员属性 - 父类和子类的行为可能不一致(originKey、propertyKeys、objectClassInArray) ****/
|
||||||
|
/** 设置最原始的key */
|
||||||
|
- (void)setOriginKey:(id)originKey forClass:(Class)c;
|
||||||
|
/** 对应着字典中的多级key(里面存放的数组,数组里面都是MJPropertyKey对象) */
|
||||||
|
- (NSArray *)propertyKeysForClass:(Class)c;
|
||||||
|
|
||||||
|
/** 模型数组中的模型类型 */
|
||||||
|
- (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c;
|
||||||
|
- (Class)objectClassInArrayForClass:(Class)c;
|
||||||
|
/**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置object的成员变量值
|
||||||
|
*/
|
||||||
|
- (void)setValue:(id)value forObject:(id)object;
|
||||||
|
/**
|
||||||
|
* 得到object的成员属性值
|
||||||
|
*/
|
||||||
|
- (id)valueForObject:(id)object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*/
|
||||||
|
+ (instancetype)cachedPropertyWithProperty:(objc_property_t)property;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,211 @@
|
||||||
|
//
|
||||||
|
// MJProperty.m
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/4/17.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MJProperty.h"
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
#import <objc/message.h>
|
||||||
|
#include "TargetConditionals.h"
|
||||||
|
|
||||||
|
@interface MJProperty()
|
||||||
|
@property (strong, nonatomic) NSMutableDictionary *propertyKeysDict;
|
||||||
|
@property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict;
|
||||||
|
@property (strong, nonatomic) dispatch_semaphore_t propertyKeysLock;
|
||||||
|
@property (strong, nonatomic) dispatch_semaphore_t objectClassInArrayLock;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MJProperty
|
||||||
|
|
||||||
|
#pragma mark - 初始化
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_propertyKeysDict = [NSMutableDictionary dictionary];
|
||||||
|
_objectClassInArrayDict = [NSMutableDictionary dictionary];
|
||||||
|
_propertyKeysLock = dispatch_semaphore_create(1);
|
||||||
|
_objectClassInArrayLock = dispatch_semaphore_create(1);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 缓存
|
||||||
|
+ (instancetype)cachedPropertyWithProperty:(objc_property_t)property
|
||||||
|
{
|
||||||
|
MJProperty *propertyObj = objc_getAssociatedObject(self, property);
|
||||||
|
if (propertyObj == nil) {
|
||||||
|
propertyObj = [[self alloc] init];
|
||||||
|
propertyObj.property = property;
|
||||||
|
objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
}
|
||||||
|
return propertyObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 公共方法
|
||||||
|
- (void)setProperty:(objc_property_t)property
|
||||||
|
{
|
||||||
|
_property = property;
|
||||||
|
|
||||||
|
MJExtensionAssertParamNotNil(property);
|
||||||
|
|
||||||
|
// 1.属性名
|
||||||
|
_name = @(property_getName(property));
|
||||||
|
|
||||||
|
// 2.成员类型
|
||||||
|
NSString *attrs = @(property_getAttributes(property));
|
||||||
|
NSUInteger dotLoc = [attrs rangeOfString:@","].location;
|
||||||
|
NSString *code = nil;
|
||||||
|
NSUInteger loc = 1;
|
||||||
|
if (dotLoc == NSNotFound) { // 没有,
|
||||||
|
code = [attrs substringFromIndex:loc];
|
||||||
|
} else {
|
||||||
|
code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc)];
|
||||||
|
}
|
||||||
|
_type = [MJPropertyType cachedTypeWithCode:code];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得成员变量的值
|
||||||
|
*/
|
||||||
|
- (id)valueForObject:(id)object
|
||||||
|
{
|
||||||
|
if (self.type.KVCDisabled) return [NSNull null];
|
||||||
|
|
||||||
|
id value = [object valueForKey:self.name];
|
||||||
|
|
||||||
|
// 32位BOOL类型转换json后成Int类型
|
||||||
|
/** https://github.com/CoderMJLee/MJExtension/issues/545 */
|
||||||
|
// 32 bit device OR 32 bit Simulator
|
||||||
|
#if defined(__arm__) || (TARGET_OS_SIMULATOR && !__LP64__)
|
||||||
|
if (self.type.isBoolType) {
|
||||||
|
value = @([(NSNumber *)value boolValue]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置成员变量的值
|
||||||
|
*/
|
||||||
|
- (void)setValue:(id)value forObject:(id)object
|
||||||
|
{
|
||||||
|
if (self.type.KVCDisabled || value == nil) return;
|
||||||
|
[object setValue:value forKey:self.name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过字符串key创建对应的keys
|
||||||
|
*/
|
||||||
|
- (NSArray *)propertyKeysWithStringKey:(NSString *)stringKey
|
||||||
|
{
|
||||||
|
if (stringKey.length == 0) return nil;
|
||||||
|
|
||||||
|
NSMutableArray *propertyKeys = [NSMutableArray array];
|
||||||
|
// 如果有多级映射
|
||||||
|
NSArray *oldKeys = [stringKey componentsSeparatedByString:@"."];
|
||||||
|
|
||||||
|
for (NSString *oldKey in oldKeys) {
|
||||||
|
NSUInteger start = [oldKey rangeOfString:@"["].location;
|
||||||
|
if (start != NSNotFound) { // 有索引的key
|
||||||
|
NSString *prefixKey = [oldKey substringToIndex:start];
|
||||||
|
NSString *indexKey = prefixKey;
|
||||||
|
if (prefixKey.length) {
|
||||||
|
MJPropertyKey *propertyKey = [[MJPropertyKey alloc] init];
|
||||||
|
propertyKey.name = prefixKey;
|
||||||
|
[propertyKeys addObject:propertyKey];
|
||||||
|
|
||||||
|
indexKey = [oldKey stringByReplacingOccurrencesOfString:prefixKey withString:@""];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 解析索引 **/
|
||||||
|
// 元素
|
||||||
|
NSArray *cmps = [[indexKey stringByReplacingOccurrencesOfString:@"[" withString:@""] componentsSeparatedByString:@"]"];
|
||||||
|
for (NSInteger i = 0; i<cmps.count - 1; i++) {
|
||||||
|
MJPropertyKey *subPropertyKey = [[MJPropertyKey alloc] init];
|
||||||
|
subPropertyKey.type = MJPropertyKeyTypeArray;
|
||||||
|
subPropertyKey.name = cmps[i];
|
||||||
|
[propertyKeys addObject:subPropertyKey];
|
||||||
|
}
|
||||||
|
} else { // 没有索引的key
|
||||||
|
MJPropertyKey *propertyKey = [[MJPropertyKey alloc] init];
|
||||||
|
propertyKey.name = oldKey;
|
||||||
|
[propertyKeys addObject:propertyKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return propertyKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 对应着字典中的key */
|
||||||
|
- (void)setOriginKey:(id)originKey forClass:(Class)c
|
||||||
|
{
|
||||||
|
if ([originKey isKindOfClass:[NSString class]]) { // 字符串类型的key
|
||||||
|
NSArray *propertyKeys = [self propertyKeysWithStringKey:originKey];
|
||||||
|
if (propertyKeys.count) {
|
||||||
|
[self setPropertyKeys:@[propertyKeys] forClass:c];
|
||||||
|
}
|
||||||
|
} else if ([originKey isKindOfClass:[NSArray class]]) {
|
||||||
|
NSMutableArray *keyses = [NSMutableArray array];
|
||||||
|
for (NSString *stringKey in originKey) {
|
||||||
|
NSArray *propertyKeys = [self propertyKeysWithStringKey:stringKey];
|
||||||
|
if (propertyKeys.count) {
|
||||||
|
[keyses addObject:propertyKeys];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyses.count) {
|
||||||
|
[self setPropertyKeys:keyses forClass:c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 对应着字典中的多级key */
|
||||||
|
- (void)setPropertyKeys:(NSArray *)propertyKeys forClass:(Class)c
|
||||||
|
{
|
||||||
|
if (propertyKeys.count == 0) return;
|
||||||
|
NSString *key = NSStringFromClass(c);
|
||||||
|
if (!key) return;
|
||||||
|
|
||||||
|
MJ_LOCK(self.propertyKeysLock);
|
||||||
|
self.propertyKeysDict[key] = propertyKeys;
|
||||||
|
MJ_UNLOCK(self.propertyKeysLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)propertyKeysForClass:(Class)c
|
||||||
|
{
|
||||||
|
NSString *key = NSStringFromClass(c);
|
||||||
|
if (!key) return nil;
|
||||||
|
|
||||||
|
MJ_LOCK(self.propertyKeysLock);
|
||||||
|
NSArray *propertyKeys = self.propertyKeysDict[key];
|
||||||
|
MJ_UNLOCK(self.propertyKeysLock);
|
||||||
|
return propertyKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 模型数组中的模型类型 */
|
||||||
|
- (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c
|
||||||
|
{
|
||||||
|
if (!objectClass) return;
|
||||||
|
NSString *key = NSStringFromClass(c);
|
||||||
|
if (!key) return;
|
||||||
|
|
||||||
|
MJ_LOCK(self.objectClassInArrayLock);
|
||||||
|
self.objectClassInArrayDict[key] = objectClass;
|
||||||
|
MJ_UNLOCK(self.objectClassInArrayLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (Class)objectClassInArrayForClass:(Class)c
|
||||||
|
{
|
||||||
|
NSString *key = NSStringFromClass(c);
|
||||||
|
if (!key) return nil;
|
||||||
|
|
||||||
|
MJ_LOCK(self.objectClassInArrayLock);
|
||||||
|
Class objectClass = self.objectClassInArrayDict[key];
|
||||||
|
MJ_UNLOCK(self.objectClassInArrayLock);
|
||||||
|
return objectClass;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// MJPropertyKey.h
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/8/11.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MJPropertyKeyTypeDictionary = 0, // 字典的key
|
||||||
|
MJPropertyKeyTypeArray // 数组的key
|
||||||
|
} MJPropertyKeyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性的key
|
||||||
|
*/
|
||||||
|
@interface MJPropertyKey : NSObject
|
||||||
|
/** key的名字 */
|
||||||
|
@property (copy, nonatomic) NSString *name;
|
||||||
|
/** key的种类,可能是@"10",可能是@"age" */
|
||||||
|
@property (assign, nonatomic) MJPropertyKeyType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据当前的key,也就是name,从object(字典或者数组)中取值
|
||||||
|
*/
|
||||||
|
- (id)valueInObject:(id)object;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// MJPropertyKey.m
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/8/11.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MJPropertyKey.h"
|
||||||
|
|
||||||
|
@implementation MJPropertyKey
|
||||||
|
|
||||||
|
- (id)valueInObject:(id)object
|
||||||
|
{
|
||||||
|
if ([object isKindOfClass:[NSDictionary class]] && self.type == MJPropertyKeyTypeDictionary) {
|
||||||
|
return object[self.name];
|
||||||
|
} else if ([object isKindOfClass:[NSArray class]] && self.type == MJPropertyKeyTypeArray) {
|
||||||
|
NSArray *array = object;
|
||||||
|
NSUInteger index = self.name.intValue;
|
||||||
|
if (index < array.count) return array[index];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// MJPropertyType.h
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 14-1-15.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
// 包装一种类型
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包装一种类型
|
||||||
|
*/
|
||||||
|
@interface MJPropertyType : NSObject
|
||||||
|
/** 类型标识符 */
|
||||||
|
@property (nonatomic, copy) NSString *code;
|
||||||
|
|
||||||
|
/** 是否为id类型 */
|
||||||
|
@property (nonatomic, readonly, getter=isIdType) BOOL idType;
|
||||||
|
|
||||||
|
/** 是否为基本数字类型:int、float等 */
|
||||||
|
@property (nonatomic, readonly, getter=isNumberType) BOOL numberType;
|
||||||
|
|
||||||
|
/** 是否为BOOL类型 */
|
||||||
|
@property (nonatomic, readonly, getter=isBoolType) BOOL boolType;
|
||||||
|
|
||||||
|
/** 对象类型(如果是基本数据类型,此值为nil) */
|
||||||
|
@property (nonatomic, readonly) Class typeClass;
|
||||||
|
|
||||||
|
/** 类型是否来自于Foundation框架,比如NSString、NSArray */
|
||||||
|
@property (nonatomic, readonly, getter = isFromFoundation) BOOL fromFoundation;
|
||||||
|
/** 类型是否不支持KVC */
|
||||||
|
@property (nonatomic, readonly, getter = isKVCDisabled) BOOL KVCDisabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的类型对象
|
||||||
|
*/
|
||||||
|
+ (instancetype)cachedTypeWithCode:(NSString *)code;
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
//
|
||||||
|
// MJPropertyType.m
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 14-1-15.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MJPropertyType.h"
|
||||||
|
#import "MJExtension.h"
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
|
||||||
|
@implementation MJPropertyType
|
||||||
|
|
||||||
|
+ (instancetype)cachedTypeWithCode:(NSString *)code
|
||||||
|
{
|
||||||
|
MJExtensionAssertParamNotNil2(code, nil);
|
||||||
|
|
||||||
|
static NSMutableDictionary *types;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
types = [NSMutableDictionary dictionary];
|
||||||
|
});
|
||||||
|
|
||||||
|
MJPropertyType *type = types[code];
|
||||||
|
if (type == nil) {
|
||||||
|
type = [[self alloc] init];
|
||||||
|
type.code = code;
|
||||||
|
types[code] = type;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 公共方法
|
||||||
|
- (void)setCode:(NSString *)code
|
||||||
|
{
|
||||||
|
_code = code;
|
||||||
|
|
||||||
|
MJExtensionAssertParamNotNil(code);
|
||||||
|
|
||||||
|
if ([code isEqualToString:MJPropertyTypeId]) {
|
||||||
|
_idType = YES;
|
||||||
|
} else if (code.length == 0) {
|
||||||
|
_KVCDisabled = YES;
|
||||||
|
} else if (code.length > 3 && [code hasPrefix:@"@\""]) {
|
||||||
|
// 去掉@"和",截取中间的类型名称
|
||||||
|
_code = [code substringWithRange:NSMakeRange(2, code.length - 3)];
|
||||||
|
_typeClass = NSClassFromString(_code);
|
||||||
|
_fromFoundation = [MJFoundation isClassFromFoundation:_typeClass];
|
||||||
|
_numberType = [_typeClass isSubclassOfClass:[NSNumber class]];
|
||||||
|
|
||||||
|
} else if ([code isEqualToString:MJPropertyTypeSEL] ||
|
||||||
|
[code isEqualToString:MJPropertyTypeIvar] ||
|
||||||
|
[code isEqualToString:MJPropertyTypeMethod]) {
|
||||||
|
_KVCDisabled = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否为数字类型
|
||||||
|
NSString *lowerCode = _code.lowercaseString;
|
||||||
|
NSArray *numberTypes = @[MJPropertyTypeInt, MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar];
|
||||||
|
if ([numberTypes containsObject:lowerCode]) {
|
||||||
|
_numberType = YES;
|
||||||
|
|
||||||
|
if ([lowerCode isEqualToString:MJPropertyTypeBOOL1]
|
||||||
|
|| [lowerCode isEqualToString:MJPropertyTypeBOOL2]) {
|
||||||
|
_boolType = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJClass.h
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/8/11.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历所有类的block(父类)
|
||||||
|
*/
|
||||||
|
typedef void (^MJClassesEnumeration)(Class c, BOOL *stop);
|
||||||
|
|
||||||
|
/** 这个数组中的属性名才会进行字典和模型的转换 */
|
||||||
|
typedef NSArray * (^MJAllowedPropertyNames)(void);
|
||||||
|
/** 这个数组中的属性名才会进行归档 */
|
||||||
|
typedef NSArray * (^MJAllowedCodingPropertyNames)(void);
|
||||||
|
|
||||||
|
/** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */
|
||||||
|
typedef NSArray * (^MJIgnoredPropertyNames)(void);
|
||||||
|
/** 这个数组中的属性名将会被忽略:不进行归档 */
|
||||||
|
typedef NSArray * (^MJIgnoredCodingPropertyNames)(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类相关的扩展
|
||||||
|
*/
|
||||||
|
@interface NSObject (MJClass)
|
||||||
|
/**
|
||||||
|
* 遍历所有的类
|
||||||
|
*/
|
||||||
|
+ (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration;
|
||||||
|
+ (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration;
|
||||||
|
|
||||||
|
#pragma mark - 属性白名单配置
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名才会进行字典和模型的转换
|
||||||
|
*
|
||||||
|
* @param allowedPropertyNames 这个数组中的属性名才会进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名才会进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_totalAllowedPropertyNames;
|
||||||
|
|
||||||
|
#pragma mark - 属性黑名单配置
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名将会被忽略:不进行字典和模型的转换
|
||||||
|
*
|
||||||
|
* @param ignoredPropertyNames 这个数组中的属性名将会被忽略:不进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名将会被忽略:不进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_totalIgnoredPropertyNames;
|
||||||
|
|
||||||
|
#pragma mark - 归档属性白名单配置
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名才会进行归档
|
||||||
|
*
|
||||||
|
* @param allowedCodingPropertyNames 这个数组中的属性名才会进行归档
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名才会进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_totalAllowedCodingPropertyNames;
|
||||||
|
|
||||||
|
#pragma mark - 归档属性黑名单配置
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名将会被忽略:不进行归档
|
||||||
|
*
|
||||||
|
* @param ignoredCodingPropertyNames 这个数组中的属性名将会被忽略:不进行归档
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名将会被忽略:不进行归档
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_totalIgnoredCodingPropertyNames;
|
||||||
|
|
||||||
|
#pragma mark - 内部使用
|
||||||
|
+ (void)mj_setupBlockReturnValue:(id (^)(void))block key:(const char *)key;
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJClass.m
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/8/11.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSObject+MJClass.h"
|
||||||
|
#import "NSObject+MJCoding.h"
|
||||||
|
#import "NSObject+MJKeyValue.h"
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
static const char MJAllowedPropertyNamesKey = '\0';
|
||||||
|
static const char MJIgnoredPropertyNamesKey = '\0';
|
||||||
|
static const char MJAllowedCodingPropertyNamesKey = '\0';
|
||||||
|
static const char MJIgnoredCodingPropertyNamesKey = '\0';
|
||||||
|
|
||||||
|
@implementation NSObject (MJClass)
|
||||||
|
|
||||||
|
+ (NSMutableDictionary *)mj_classDictForKey:(const void *)key
|
||||||
|
{
|
||||||
|
static NSMutableDictionary *allowedPropertyNamesDict;
|
||||||
|
static NSMutableDictionary *ignoredPropertyNamesDict;
|
||||||
|
static NSMutableDictionary *allowedCodingPropertyNamesDict;
|
||||||
|
static NSMutableDictionary *ignoredCodingPropertyNamesDict;
|
||||||
|
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
allowedPropertyNamesDict = [NSMutableDictionary dictionary];
|
||||||
|
ignoredPropertyNamesDict = [NSMutableDictionary dictionary];
|
||||||
|
allowedCodingPropertyNamesDict = [NSMutableDictionary dictionary];
|
||||||
|
ignoredCodingPropertyNamesDict = [NSMutableDictionary dictionary];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (key == &MJAllowedPropertyNamesKey) return allowedPropertyNamesDict;
|
||||||
|
if (key == &MJIgnoredPropertyNamesKey) return ignoredPropertyNamesDict;
|
||||||
|
if (key == &MJAllowedCodingPropertyNamesKey) return allowedCodingPropertyNamesDict;
|
||||||
|
if (key == &MJIgnoredCodingPropertyNamesKey) return ignoredCodingPropertyNamesDict;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration
|
||||||
|
{
|
||||||
|
// 1.没有block就直接返回
|
||||||
|
if (enumeration == nil) return;
|
||||||
|
|
||||||
|
// 2.停止遍历的标记
|
||||||
|
BOOL stop = NO;
|
||||||
|
|
||||||
|
// 3.当前正在遍历的类
|
||||||
|
Class c = self;
|
||||||
|
|
||||||
|
// 4.开始遍历每一个类
|
||||||
|
while (c && !stop) {
|
||||||
|
// 4.1.执行操作
|
||||||
|
enumeration(c, &stop);
|
||||||
|
|
||||||
|
// 4.2.获得父类
|
||||||
|
c = class_getSuperclass(c);
|
||||||
|
|
||||||
|
if ([MJFoundation isClassFromFoundation:c]) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration
|
||||||
|
{
|
||||||
|
// 1.没有block就直接返回
|
||||||
|
if (enumeration == nil) return;
|
||||||
|
|
||||||
|
// 2.停止遍历的标记
|
||||||
|
BOOL stop = NO;
|
||||||
|
|
||||||
|
// 3.当前正在遍历的类
|
||||||
|
Class c = self;
|
||||||
|
|
||||||
|
// 4.开始遍历每一个类
|
||||||
|
while (c && !stop) {
|
||||||
|
// 4.1.执行操作
|
||||||
|
enumeration(c, &stop);
|
||||||
|
|
||||||
|
// 4.2.获得父类
|
||||||
|
c = class_getSuperclass(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 属性黑名单配置
|
||||||
|
+ (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames
|
||||||
|
{
|
||||||
|
[self mj_setupBlockReturnValue:ignoredPropertyNames key:&MJIgnoredPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_totalIgnoredPropertyNames
|
||||||
|
{
|
||||||
|
return [self mj_totalObjectsWithSelector:@selector(mj_ignoredPropertyNames) key:&MJIgnoredPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 归档属性黑名单配置
|
||||||
|
+ (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames
|
||||||
|
{
|
||||||
|
[self mj_setupBlockReturnValue:ignoredCodingPropertyNames key:&MJIgnoredCodingPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_totalIgnoredCodingPropertyNames
|
||||||
|
{
|
||||||
|
return [self mj_totalObjectsWithSelector:@selector(mj_ignoredCodingPropertyNames) key:&MJIgnoredCodingPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 属性白名单配置
|
||||||
|
+ (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames;
|
||||||
|
{
|
||||||
|
[self mj_setupBlockReturnValue:allowedPropertyNames key:&MJAllowedPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_totalAllowedPropertyNames
|
||||||
|
{
|
||||||
|
return [self mj_totalObjectsWithSelector:@selector(mj_allowedPropertyNames) key:&MJAllowedPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 归档属性白名单配置
|
||||||
|
+ (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames
|
||||||
|
{
|
||||||
|
[self mj_setupBlockReturnValue:allowedCodingPropertyNames key:&MJAllowedCodingPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_totalAllowedCodingPropertyNames
|
||||||
|
{
|
||||||
|
return [self mj_totalObjectsWithSelector:@selector(mj_allowedCodingPropertyNames) key:&MJAllowedCodingPropertyNamesKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - block和方法处理:存储block的返回值
|
||||||
|
+ (void)mj_setupBlockReturnValue:(id (^)(void))block key:(const char *)key {
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
if (block) {
|
||||||
|
objc_setAssociatedObject(self, key, block(), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
} else {
|
||||||
|
objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空数据
|
||||||
|
[[self mj_classDictForKey:key] removeAllObjects];
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key
|
||||||
|
{
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
NSMutableArray *array = [self mj_classDictForKey:key][NSStringFromClass(self)];
|
||||||
|
if (array == nil) {
|
||||||
|
// 创建、存储
|
||||||
|
[self mj_classDictForKey:key][NSStringFromClass(self)] = array = [NSMutableArray array];
|
||||||
|
|
||||||
|
if ([self respondsToSelector:selector]) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||||
|
NSArray *subArray = [self performSelector:selector];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
if (subArray) {
|
||||||
|
[array addObjectsFromArray:subArray];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
NSArray *subArray = objc_getAssociatedObject(c, key);
|
||||||
|
[array addObjectsFromArray:subArray];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJCoding.h
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 14-1-15.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Codeing协议
|
||||||
|
*/
|
||||||
|
@protocol MJCoding <NSObject>
|
||||||
|
@optional
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名才会进行归档
|
||||||
|
*/
|
||||||
|
+ (NSArray *)mj_allowedCodingPropertyNames;
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名将会被忽略:不进行归档
|
||||||
|
*/
|
||||||
|
+ (NSArray *)mj_ignoredCodingPropertyNames;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSObject (MJCoding) <MJCoding>
|
||||||
|
/**
|
||||||
|
* 解码(从文件中解析对象)
|
||||||
|
*/
|
||||||
|
- (void)mj_decode:(NSCoder *)decoder;
|
||||||
|
/**
|
||||||
|
* 编码(将对象写入文件中)
|
||||||
|
*/
|
||||||
|
- (void)mj_encode:(NSCoder *)encoder;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/**
|
||||||
|
归档的实现
|
||||||
|
*/
|
||||||
|
#define MJCodingImplementation \
|
||||||
|
- (id)initWithCoder:(NSCoder *)decoder \
|
||||||
|
{ \
|
||||||
|
if (self = [super init]) { \
|
||||||
|
[self mj_decode:decoder]; \
|
||||||
|
} \
|
||||||
|
return self; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)encoder \
|
||||||
|
{ \
|
||||||
|
[self mj_encode:encoder]; \
|
||||||
|
}\
|
||||||
|
|
||||||
|
#define MJExtensionCodingImplementation MJCodingImplementation
|
||||||
|
|
||||||
|
#define MJSecureCodingImplementation(CLASS, FLAG) \
|
||||||
|
@interface CLASS (MJSecureCoding) <NSSecureCoding> \
|
||||||
|
@end \
|
||||||
|
@implementation CLASS (MJSecureCoding) \
|
||||||
|
MJCodingImplementation \
|
||||||
|
+ (BOOL)supportsSecureCoding { \
|
||||||
|
return FLAG; \
|
||||||
|
} \
|
||||||
|
@end \
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJCoding.m
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 14-1-15.
|
||||||
|
// Copyright (c) 2014年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSObject+MJCoding.h"
|
||||||
|
#import "NSObject+MJClass.h"
|
||||||
|
#import "NSObject+MJProperty.h"
|
||||||
|
#import "MJProperty.h"
|
||||||
|
|
||||||
|
@implementation NSObject (MJCoding)
|
||||||
|
|
||||||
|
- (void)mj_encode:(NSCoder *)encoder
|
||||||
|
{
|
||||||
|
Class clazz = [self class];
|
||||||
|
|
||||||
|
NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames];
|
||||||
|
NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames];
|
||||||
|
|
||||||
|
[clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
|
||||||
|
// 检测是否被忽略
|
||||||
|
if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return;
|
||||||
|
if ([ignoredCodingPropertyNames containsObject:property.name]) return;
|
||||||
|
|
||||||
|
id value = [property valueForObject:self];
|
||||||
|
if (value == nil) return;
|
||||||
|
[encoder encodeObject:value forKey:property.name];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mj_decode:(NSCoder *)decoder
|
||||||
|
{
|
||||||
|
Class clazz = [self class];
|
||||||
|
|
||||||
|
NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames];
|
||||||
|
NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames];
|
||||||
|
|
||||||
|
[clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
|
||||||
|
// 检测是否被忽略
|
||||||
|
if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return;
|
||||||
|
if ([ignoredCodingPropertyNames containsObject:property.name]) return;
|
||||||
|
|
||||||
|
// fixed `-[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSNumber'(This will be disallowed in the future.)` warning.
|
||||||
|
Class genericClass = [property objectClassInArrayForClass:property.srcClass];
|
||||||
|
// If genericClass exists, property.type.typeClass would be a collection type(Array, Set, Dictionary). This scenario([obj, nil, obj, nil]) would not happened.
|
||||||
|
NSSet *classes = [NSSet setWithObjects:NSNumber.class,
|
||||||
|
property.type.typeClass, genericClass, nil];
|
||||||
|
id value = [decoder decodeObjectOfClasses:classes forKey:property.name];
|
||||||
|
if (value == nil) { // 兼容以前的MJExtension版本
|
||||||
|
value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]];
|
||||||
|
}
|
||||||
|
if (value == nil) return;
|
||||||
|
[property setValue:value forObject:self];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJKeyValue.h
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 13-8-24.
|
||||||
|
// Copyright (c) 2013年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
#import <CoreData/CoreData.h>
|
||||||
|
#import "MJProperty.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyValue协议
|
||||||
|
*/
|
||||||
|
@protocol MJKeyValue <NSObject>
|
||||||
|
@optional
|
||||||
|
/**
|
||||||
|
* 只有这个数组中的属性名才允许进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (NSArray *)mj_allowedPropertyNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这个数组中的属性名将会被忽略:不进行字典和模型的转换
|
||||||
|
*/
|
||||||
|
+ (NSArray *)mj_ignoredPropertyNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将属性名换为其他key去字典中取值
|
||||||
|
*
|
||||||
|
* @return 字典中的key是属性名,value是从字典中取值用的key
|
||||||
|
*/
|
||||||
|
+ (NSDictionary *)mj_replacedKeyFromPropertyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将属性名换为其他key去字典中取值
|
||||||
|
*
|
||||||
|
* @return 从字典中取值用的key
|
||||||
|
*/
|
||||||
|
+ (id)mj_replacedKeyFromPropertyName121:(NSString *)propertyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组中需要转换的模型类
|
||||||
|
*
|
||||||
|
* @return 字典中的key是数组属性名,value是数组中存放模型的Class(Class类型或者NSString类型)
|
||||||
|
*/
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray;
|
||||||
|
|
||||||
|
|
||||||
|
/** 特殊地区在字符串格式化数字时使用 */
|
||||||
|
+ (NSLocale *)mj_numberLocale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旧值换新值,用于过滤字典中的值
|
||||||
|
*
|
||||||
|
* @param oldValue 旧值
|
||||||
|
*
|
||||||
|
* @return 新值
|
||||||
|
*/
|
||||||
|
- (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当字典转模型完毕时调用
|
||||||
|
*/
|
||||||
|
- (void)mj_keyValuesDidFinishConvertingToObject MJExtensionDeprecated("请使用`mj_didConvertToObjectWithKeyValues:`替代");
|
||||||
|
- (void)mj_keyValuesDidFinishConvertingToObject:(NSDictionary *)keyValues MJExtensionDeprecated("请使用`mj_didConvertToObjectWithKeyValues:`替代");
|
||||||
|
- (void)mj_didConvertToObjectWithKeyValues:(NSDictionary *)keyValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当模型转字典完毕时调用
|
||||||
|
*/
|
||||||
|
- (void)mj_objectDidFinishConvertingToKeyValues MJExtensionDeprecated("请使用`mj_objectDidConvertToKeyValues:`替代");
|
||||||
|
- (void)mj_objectDidConvertToKeyValues:(NSMutableDictionary *)keyValues;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSObject (MJKeyValue) <MJKeyValue>
|
||||||
|
#pragma mark - 类方法
|
||||||
|
/**
|
||||||
|
* 字典转模型过程中遇到的错误
|
||||||
|
*/
|
||||||
|
+ (NSError *)mj_error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来)
|
||||||
|
*/
|
||||||
|
+ (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference;
|
||||||
|
|
||||||
|
#pragma mark - 对象方法
|
||||||
|
/**
|
||||||
|
* 将字典的键值对转成模型属性
|
||||||
|
* @param keyValues 字典(可以是NSDictionary、NSData、NSString)
|
||||||
|
*/
|
||||||
|
- (instancetype)mj_setKeyValues:(id)keyValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字典的键值对转成模型属性
|
||||||
|
* @param keyValues 字典(可以是NSDictionary、NSData、NSString)
|
||||||
|
* @param context CoreData上下文
|
||||||
|
*/
|
||||||
|
- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将模型转成字典
|
||||||
|
* @return 字典
|
||||||
|
*/
|
||||||
|
- (NSMutableDictionary *)mj_keyValues;
|
||||||
|
- (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys;
|
||||||
|
- (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过模型数组来创建一个字典数组
|
||||||
|
* @param objectArray 模型数组
|
||||||
|
* @return 字典数组
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray;
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys;
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys;
|
||||||
|
|
||||||
|
#pragma mark - 字典转模型
|
||||||
|
/**
|
||||||
|
* 通过字典来创建一个模型
|
||||||
|
* @param keyValues 字典(可以是NSDictionary、NSData、NSString)
|
||||||
|
* @return 新建的对象
|
||||||
|
*/
|
||||||
|
+ (instancetype)mj_objectWithKeyValues:(id)keyValues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过字典来创建一个CoreData模型
|
||||||
|
* @param keyValues 字典(可以是NSDictionary、NSData、NSString)
|
||||||
|
* @param context CoreData上下文
|
||||||
|
* @return 新建的对象
|
||||||
|
*/
|
||||||
|
+ (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过plist来创建一个模型
|
||||||
|
* @param filename 文件名(仅限于mainBundle中的文件)
|
||||||
|
* @return 新建的对象
|
||||||
|
*/
|
||||||
|
+ (instancetype)mj_objectWithFilename:(NSString *)filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过plist来创建一个模型
|
||||||
|
* @param file 文件全路径
|
||||||
|
* @return 新建的对象
|
||||||
|
*/
|
||||||
|
+ (instancetype)mj_objectWithFile:(NSString *)file;
|
||||||
|
|
||||||
|
#pragma mark - 字典数组转模型数组
|
||||||
|
/**
|
||||||
|
* 通过字典数组来创建一个模型数组
|
||||||
|
* @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString)
|
||||||
|
* @return 模型数组
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过字典数组来创建一个模型数组
|
||||||
|
* @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString)
|
||||||
|
* @param context CoreData上下文
|
||||||
|
* @return 模型数组
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过plist来创建一个模型数组
|
||||||
|
* @param filename 文件名(仅限于mainBundle中的文件)
|
||||||
|
* @return 模型数组
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过plist来创建一个模型数组
|
||||||
|
* @param file 文件全路径
|
||||||
|
* @return 模型数组
|
||||||
|
*/
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file;
|
||||||
|
|
||||||
|
#pragma mark - 转换为JSON
|
||||||
|
/**
|
||||||
|
* 转换为JSON Data
|
||||||
|
*/
|
||||||
|
- (NSData *)mj_JSONData;
|
||||||
|
/**
|
||||||
|
* 转换为字典或者数组
|
||||||
|
*/
|
||||||
|
- (id)mj_JSONObject;
|
||||||
|
/**
|
||||||
|
* 转换为JSON 字符串
|
||||||
|
*/
|
||||||
|
- (NSString *)mj_JSONString;
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,524 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJKeyValue.m
|
||||||
|
// MJExtension
|
||||||
|
//
|
||||||
|
// Created by mj on 13-8-24.
|
||||||
|
// Copyright (c) 2013年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSObject+MJKeyValue.h"
|
||||||
|
#import "NSObject+MJProperty.h"
|
||||||
|
#import "NSString+MJExtension.h"
|
||||||
|
#import "MJProperty.h"
|
||||||
|
#import "MJPropertyType.h"
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
#import "NSString+MJExtension.h"
|
||||||
|
#import "NSObject+MJClass.h"
|
||||||
|
|
||||||
|
@implementation NSDecimalNumber(MJKeyValue)
|
||||||
|
|
||||||
|
- (id)mj_standardValueWithTypeCode:(NSString *)typeCode {
|
||||||
|
// 由于这里涉及到编译器问题, 暂时保留 Long, 实际上在 64 位系统上, 这 2 个精度范围相同,
|
||||||
|
// 32 位略有不同, 其余都可使用 Double 进行强转不丢失精度
|
||||||
|
if ([typeCode isEqualToString:MJPropertyTypeLongLong]) {
|
||||||
|
return @(self.longLongValue);
|
||||||
|
} else if ([typeCode isEqualToString:MJPropertyTypeLongLong.uppercaseString]) {
|
||||||
|
return @(self.unsignedLongLongValue);
|
||||||
|
} else if ([typeCode isEqualToString:MJPropertyTypeLong]) {
|
||||||
|
return @(self.longValue);
|
||||||
|
} else if ([typeCode isEqualToString:MJPropertyTypeLong.uppercaseString]) {
|
||||||
|
return @(self.unsignedLongValue);
|
||||||
|
} else {
|
||||||
|
return @(self.doubleValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSObject (MJKeyValue)
|
||||||
|
|
||||||
|
#pragma mark - 错误
|
||||||
|
static const char MJErrorKey = '\0';
|
||||||
|
+ (NSError *)mj_error
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(self, &MJErrorKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setMj_error:(NSError *)error
|
||||||
|
{
|
||||||
|
objc_setAssociatedObject(self, &MJErrorKey, error, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 模型 -> 字典时的参考
|
||||||
|
/** 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) */
|
||||||
|
static const char MJReferenceReplacedKeyWhenCreatingKeyValuesKey = '\0';
|
||||||
|
|
||||||
|
+ (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference
|
||||||
|
{
|
||||||
|
objc_setAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey, @(reference), OBJC_ASSOCIATION_ASSIGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)mj_isReferenceReplacedKeyWhenCreatingKeyValues
|
||||||
|
{
|
||||||
|
__block id value = objc_getAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey);
|
||||||
|
if (!value) {
|
||||||
|
[self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
value = objc_getAssociatedObject(c, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey);
|
||||||
|
|
||||||
|
if (value) *stop = YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return [value boolValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - --常用的对象--
|
||||||
|
+ (void)load
|
||||||
|
{
|
||||||
|
// 默认设置
|
||||||
|
[self mj_referenceReplacedKeyWhenCreatingKeyValues:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - --公共方法--
|
||||||
|
#pragma mark - 字典 -> 模型
|
||||||
|
- (instancetype)mj_setKeyValues:(id)keyValues
|
||||||
|
{
|
||||||
|
return [self mj_setKeyValues:keyValues context:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
核心代码:
|
||||||
|
*/
|
||||||
|
- (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
|
||||||
|
{
|
||||||
|
// 获得JSON对象
|
||||||
|
keyValues = [keyValues mj_JSONObject];
|
||||||
|
|
||||||
|
MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, [self class], @"keyValues参数不是一个字典");
|
||||||
|
|
||||||
|
Class clazz = [self class];
|
||||||
|
NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames];
|
||||||
|
NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames];
|
||||||
|
|
||||||
|
NSLocale *numberLocale = nil;
|
||||||
|
if ([self.class respondsToSelector:@selector(mj_numberLocale)]) {
|
||||||
|
numberLocale = self.class.mj_numberLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。
|
||||||
|
[clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
|
||||||
|
@try {
|
||||||
|
// 0.检测是否被忽略
|
||||||
|
if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
|
||||||
|
if ([ignoredPropertyNames containsObject:property.name]) return;
|
||||||
|
|
||||||
|
// 1.取出属性值
|
||||||
|
id value;
|
||||||
|
NSArray *propertyKeyses = [property propertyKeysForClass:clazz];
|
||||||
|
for (NSArray *propertyKeys in propertyKeyses) {
|
||||||
|
value = keyValues;
|
||||||
|
for (MJPropertyKey *propertyKey in propertyKeys) {
|
||||||
|
value = [propertyKey valueInObject:value];
|
||||||
|
}
|
||||||
|
if (value) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 值的过滤
|
||||||
|
id newValue = [clazz mj_getNewValueFromObject:self oldValue:value property:property];
|
||||||
|
if (newValue != value) { // 有过滤后的新值
|
||||||
|
[property setValue:newValue forObject:self];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有值,就直接返回
|
||||||
|
if (!value || value == [NSNull null]) return;
|
||||||
|
|
||||||
|
// 2.复杂处理
|
||||||
|
MJPropertyType *type = property.type;
|
||||||
|
Class propertyClass = type.typeClass;
|
||||||
|
Class objectClass = [property objectClassInArrayForClass:[self class]];
|
||||||
|
|
||||||
|
// 不可变 -> 可变处理
|
||||||
|
if (propertyClass == [NSMutableArray class] && [value isKindOfClass:[NSArray class]]) {
|
||||||
|
value = [NSMutableArray arrayWithArray:value];
|
||||||
|
} else if (propertyClass == [NSMutableDictionary class] && [value isKindOfClass:[NSDictionary class]]) {
|
||||||
|
value = [NSMutableDictionary dictionaryWithDictionary:value];
|
||||||
|
} else if (propertyClass == [NSMutableString class] && [value isKindOfClass:[NSString class]]) {
|
||||||
|
value = [NSMutableString stringWithString:value];
|
||||||
|
} else if (propertyClass == [NSMutableData class] && [value isKindOfClass:[NSData class]]) {
|
||||||
|
value = [NSMutableData dataWithData:value];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.isFromFoundation && propertyClass) { // 模型属性
|
||||||
|
value = [propertyClass mj_objectWithKeyValues:value context:context];
|
||||||
|
} else if (objectClass) {
|
||||||
|
if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) {
|
||||||
|
// string array -> url array
|
||||||
|
NSMutableArray *urlArray = [NSMutableArray array];
|
||||||
|
for (NSString *string in value) {
|
||||||
|
if (![string isKindOfClass:[NSString class]]) continue;
|
||||||
|
[urlArray addObject:string.mj_url];
|
||||||
|
}
|
||||||
|
value = urlArray;
|
||||||
|
} else { // 字典数组-->模型数组
|
||||||
|
value = [objectClass mj_objectArrayWithKeyValuesArray:value context:context];
|
||||||
|
}
|
||||||
|
} else if (propertyClass == [NSString class]) {
|
||||||
|
if ([value isKindOfClass:[NSNumber class]]) {
|
||||||
|
// NSNumber -> NSString
|
||||||
|
value = [value description];
|
||||||
|
} else if ([value isKindOfClass:[NSURL class]]) {
|
||||||
|
// NSURL -> NSString
|
||||||
|
value = [value absoluteString];
|
||||||
|
}
|
||||||
|
} else if ([value isKindOfClass:[NSString class]]) {
|
||||||
|
if (propertyClass == [NSURL class]) {
|
||||||
|
// NSString -> NSURL
|
||||||
|
// 字符串转码
|
||||||
|
value = [value mj_url];
|
||||||
|
} else if (type.isNumberType) {
|
||||||
|
NSString *oldValue = value;
|
||||||
|
|
||||||
|
// NSString -> NSDecimalNumber, 使用 DecimalNumber 来转换数字, 避免丢失精度以及溢出
|
||||||
|
NSDecimalNumber *decimalValue = [NSDecimalNumber decimalNumberWithString:oldValue
|
||||||
|
locale:numberLocale];
|
||||||
|
|
||||||
|
// 检查特殊情况
|
||||||
|
if (decimalValue == NSDecimalNumber.notANumber) {
|
||||||
|
value = @(0);
|
||||||
|
}else if (propertyClass != [NSDecimalNumber class]) {
|
||||||
|
value = [decimalValue mj_standardValueWithTypeCode:type.code];
|
||||||
|
} else {
|
||||||
|
value = decimalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是BOOL
|
||||||
|
if (type.isBoolType) {
|
||||||
|
// 字符串转BOOL(字符串没有charValue方法)
|
||||||
|
// 系统会调用字符串的charValue转为BOOL类型
|
||||||
|
NSString *lower = [oldValue lowercaseString];
|
||||||
|
if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) {
|
||||||
|
value = @YES;
|
||||||
|
} else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) {
|
||||||
|
value = @NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ([value isKindOfClass:[NSNumber class]] && propertyClass == [NSDecimalNumber class]){
|
||||||
|
// 过滤 NSDecimalNumber类型
|
||||||
|
if (![value isKindOfClass:[NSDecimalNumber class]]) {
|
||||||
|
value = [NSDecimalNumber decimalNumberWithDecimal:[((NSNumber *)value) decimalValue]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 经过转换后, 最终检查 value 与 property 是否匹配
|
||||||
|
if (propertyClass && ![value isKindOfClass:propertyClass]) {
|
||||||
|
value = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.赋值
|
||||||
|
[property setValue:value forObject:self];
|
||||||
|
} @catch (NSException *exception) {
|
||||||
|
MJExtensionBuildError([self class], exception.reason);
|
||||||
|
MJExtensionLog(@"%@", exception);
|
||||||
|
#ifdef DEBUG
|
||||||
|
[exception raise];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 转换完毕
|
||||||
|
if ([self respondsToSelector:@selector(mj_didConvertToObjectWithKeyValues:)]) {
|
||||||
|
[self mj_didConvertToObjectWithKeyValues:keyValues];
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
|
||||||
|
if ([self respondsToSelector:@selector(mj_keyValuesDidFinishConvertingToObject)]) {
|
||||||
|
[self mj_keyValuesDidFinishConvertingToObject];
|
||||||
|
}
|
||||||
|
if ([self respondsToSelector:@selector(mj_keyValuesDidFinishConvertingToObject:)]) {
|
||||||
|
[self mj_keyValuesDidFinishConvertingToObject:keyValues];
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)mj_objectWithKeyValues:(id)keyValues
|
||||||
|
{
|
||||||
|
return [self mj_objectWithKeyValues:keyValues context:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context
|
||||||
|
{
|
||||||
|
// 获得JSON对象
|
||||||
|
keyValues = [keyValues mj_JSONObject];
|
||||||
|
MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], nil, [self class], @"keyValues参数不是一个字典");
|
||||||
|
|
||||||
|
if ([self isSubclassOfClass:[NSManagedObject class]] && context) {
|
||||||
|
NSString *entityName = [(NSManagedObject *)self entity].name;
|
||||||
|
return [[NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context] mj_setKeyValues:keyValues context:context];
|
||||||
|
}
|
||||||
|
return [[[self alloc] init] mj_setKeyValues:keyValues];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)mj_objectWithFilename:(NSString *)filename
|
||||||
|
{
|
||||||
|
MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil");
|
||||||
|
|
||||||
|
return [self mj_objectWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (instancetype)mj_objectWithFile:(NSString *)file
|
||||||
|
{
|
||||||
|
MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil");
|
||||||
|
|
||||||
|
return [self mj_objectWithKeyValues:[NSDictionary dictionaryWithContentsOfFile:file]];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 字典数组 -> 模型数组
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray
|
||||||
|
{
|
||||||
|
return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context
|
||||||
|
{
|
||||||
|
// 如果是JSON字符串
|
||||||
|
keyValuesArray = [keyValuesArray mj_JSONObject];
|
||||||
|
|
||||||
|
// 1.判断真实性
|
||||||
|
MJExtensionAssertError([keyValuesArray isKindOfClass:[NSArray class]], nil, [self class], @"keyValuesArray参数不是一个数组");
|
||||||
|
|
||||||
|
// 如果数组里面放的是NSString、NSNumber等数据
|
||||||
|
if ([MJFoundation isClassFromFoundation:self]) return [NSMutableArray arrayWithArray:keyValuesArray];
|
||||||
|
|
||||||
|
|
||||||
|
// 2.创建数组
|
||||||
|
NSMutableArray *modelArray = [NSMutableArray array];
|
||||||
|
|
||||||
|
// 3.遍历
|
||||||
|
for (NSDictionary *keyValues in keyValuesArray) {
|
||||||
|
if ([keyValues isKindOfClass:[NSArray class]]){
|
||||||
|
[modelArray addObject:[self mj_objectArrayWithKeyValuesArray:keyValues context:context]];
|
||||||
|
} else {
|
||||||
|
id model = [self mj_objectWithKeyValues:keyValues context:context];
|
||||||
|
if (model) [modelArray addObject:model];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modelArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename
|
||||||
|
{
|
||||||
|
MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil");
|
||||||
|
|
||||||
|
return [self mj_objectArrayWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file
|
||||||
|
{
|
||||||
|
MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil");
|
||||||
|
|
||||||
|
return [self mj_objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:file]];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 模型 -> 字典
|
||||||
|
- (NSMutableDictionary *)mj_keyValues
|
||||||
|
{
|
||||||
|
return [self mj_keyValuesWithKeys:nil ignoredKeys:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys
|
||||||
|
{
|
||||||
|
return [self mj_keyValuesWithKeys:keys ignoredKeys:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys
|
||||||
|
{
|
||||||
|
return [self mj_keyValuesWithKeys:nil ignoredKeys:ignoredKeys];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys
|
||||||
|
{
|
||||||
|
// 如果自己不是模型类, 那就返回自己
|
||||||
|
// 模型类过滤掉 NSNull
|
||||||
|
// 唯一一个不返回自己的
|
||||||
|
if ([self isMemberOfClass:NSNull.class]) { return nil; }
|
||||||
|
// 这里虽然返回了自己, 但是其实是有报错信息的.
|
||||||
|
// TODO: 报错机制不好, 需要重做
|
||||||
|
MJExtensionAssertError(![MJFoundation isClassFromFoundation:[self class]], (NSMutableDictionary *)self, [self class], @"不是自定义的模型类")
|
||||||
|
|
||||||
|
id keyValues = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
Class clazz = [self class];
|
||||||
|
NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames];
|
||||||
|
NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames];
|
||||||
|
|
||||||
|
[clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) {
|
||||||
|
@try {
|
||||||
|
// 0.检测是否被忽略
|
||||||
|
if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return;
|
||||||
|
if ([ignoredPropertyNames containsObject:property.name]) return;
|
||||||
|
if (keys.count && ![keys containsObject:property.name]) return;
|
||||||
|
if ([ignoredKeys containsObject:property.name]) return;
|
||||||
|
|
||||||
|
// 1.取出属性值
|
||||||
|
id value = [property valueForObject:self];
|
||||||
|
if (!value) return;
|
||||||
|
|
||||||
|
// 2.如果是模型属性
|
||||||
|
MJPropertyType *type = property.type;
|
||||||
|
Class propertyClass = type.typeClass;
|
||||||
|
if (!type.isFromFoundation && propertyClass) {
|
||||||
|
value = [value mj_keyValues];
|
||||||
|
} else if ([value isKindOfClass:[NSArray class]]) {
|
||||||
|
// 3.处理数组里面有模型的情况
|
||||||
|
value = [NSObject mj_keyValuesArrayWithObjectArray:value];
|
||||||
|
} else if (propertyClass == [NSURL class]) {
|
||||||
|
value = [value absoluteString];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.赋值
|
||||||
|
if ([clazz mj_isReferenceReplacedKeyWhenCreatingKeyValues]) {
|
||||||
|
NSArray *propertyKeys = [[property propertyKeysForClass:clazz] firstObject];
|
||||||
|
NSUInteger keyCount = propertyKeys.count;
|
||||||
|
// 创建字典
|
||||||
|
__block id innerContainer = keyValues;
|
||||||
|
[propertyKeys enumerateObjectsUsingBlock:^(MJPropertyKey *propertyKey, NSUInteger idx, BOOL *stop) {
|
||||||
|
// 下一个属性
|
||||||
|
MJPropertyKey *nextPropertyKey = nil;
|
||||||
|
if (idx != keyCount - 1) {
|
||||||
|
nextPropertyKey = propertyKeys[idx + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextPropertyKey) { // 不是最后一个key
|
||||||
|
// 当前propertyKey对应的字典或者数组
|
||||||
|
id tempInnerContainer = [propertyKey valueInObject:innerContainer];
|
||||||
|
if (tempInnerContainer == nil || [tempInnerContainer isKindOfClass:[NSNull class]]) {
|
||||||
|
if (nextPropertyKey.type == MJPropertyKeyTypeDictionary) {
|
||||||
|
tempInnerContainer = [NSMutableDictionary dictionary];
|
||||||
|
} else {
|
||||||
|
tempInnerContainer = [NSMutableArray array];
|
||||||
|
}
|
||||||
|
if (propertyKey.type == MJPropertyKeyTypeDictionary) {
|
||||||
|
innerContainer[propertyKey.name] = tempInnerContainer;
|
||||||
|
} else {
|
||||||
|
innerContainer[propertyKey.name.intValue] = tempInnerContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([tempInnerContainer isKindOfClass:[NSMutableArray class]]) {
|
||||||
|
NSMutableArray *tempInnerContainerArray = tempInnerContainer;
|
||||||
|
int index = nextPropertyKey.name.intValue;
|
||||||
|
while (tempInnerContainerArray.count < index + 1) {
|
||||||
|
[tempInnerContainerArray addObject:[NSNull null]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
innerContainer = tempInnerContainer;
|
||||||
|
} else { // 最后一个key
|
||||||
|
if (propertyKey.type == MJPropertyKeyTypeDictionary) {
|
||||||
|
innerContainer[propertyKey.name] = value;
|
||||||
|
} else {
|
||||||
|
innerContainer[propertyKey.name.intValue] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
keyValues[property.name] = value;
|
||||||
|
}
|
||||||
|
} @catch (NSException *exception) {
|
||||||
|
MJExtensionBuildError([self class], exception.reason);
|
||||||
|
MJExtensionLog(@"%@", exception);
|
||||||
|
#ifdef DEBUG
|
||||||
|
[exception raise];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 转换完毕
|
||||||
|
if ([self respondsToSelector:@selector(mj_objectDidConvertToKeyValues:)]) {
|
||||||
|
[self mj_objectDidConvertToKeyValues:keyValues];
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
|
||||||
|
if ([self respondsToSelector:@selector(mj_objectDidFinishConvertingToKeyValues)]) {
|
||||||
|
[self mj_objectDidFinishConvertingToKeyValues];
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
return keyValues;
|
||||||
|
}
|
||||||
|
#pragma mark - 模型数组 -> 字典数组
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray
|
||||||
|
{
|
||||||
|
return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys
|
||||||
|
{
|
||||||
|
return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys ignoredKeys:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys
|
||||||
|
{
|
||||||
|
return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:ignoredKeys];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys
|
||||||
|
{
|
||||||
|
// 0.判断真实性
|
||||||
|
MJExtensionAssertError([objectArray isKindOfClass:[NSArray class]], nil, [self class], @"objectArray参数不是一个数组");
|
||||||
|
|
||||||
|
// 1.创建数组
|
||||||
|
NSMutableArray *keyValuesArray = [NSMutableArray array];
|
||||||
|
for (id object in objectArray) {
|
||||||
|
if (keys) {
|
||||||
|
id convertedObj = [object mj_keyValuesWithKeys:keys];
|
||||||
|
if (!convertedObj) { continue; }
|
||||||
|
[keyValuesArray addObject:convertedObj];
|
||||||
|
} else {
|
||||||
|
id convertedObj = [object mj_keyValuesWithIgnoredKeys:ignoredKeys];
|
||||||
|
if (!convertedObj) { continue; }
|
||||||
|
[keyValuesArray addObject:convertedObj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyValuesArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 转换为JSON
|
||||||
|
- (NSData *)mj_JSONData
|
||||||
|
{
|
||||||
|
if ([self isKindOfClass:[NSString class]]) {
|
||||||
|
return [((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
} else if ([self isKindOfClass:[NSData class]]) {
|
||||||
|
return (NSData *)self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [NSJSONSerialization dataWithJSONObject:[self mj_JSONObject] options:kNilOptions error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)mj_JSONObject
|
||||||
|
{
|
||||||
|
if ([self isKindOfClass:[NSString class]]) {
|
||||||
|
return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
|
||||||
|
} else if ([self isKindOfClass:[NSData class]]) {
|
||||||
|
return [NSJSONSerialization JSONObjectWithData:(NSData *)self options:kNilOptions error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.mj_keyValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)mj_JSONString
|
||||||
|
{
|
||||||
|
if ([self isKindOfClass:[NSString class]]) {
|
||||||
|
return (NSString *)self;
|
||||||
|
} else if ([self isKindOfClass:[NSData class]]) {
|
||||||
|
return [[NSString alloc] initWithData:(NSData *)self encoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [[NSString alloc] initWithData:[self mj_JSONData] encoding:NSUTF8StringEncoding];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJProperty.h
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/4/17.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
|
||||||
|
@class MJProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 遍历成员变量用的block
|
||||||
|
*
|
||||||
|
* @param property 成员的包装对象
|
||||||
|
* @param stop YES代表停止遍历,NO代表继续遍历
|
||||||
|
*/
|
||||||
|
typedef void (^MJPropertiesEnumeration)(MJProperty *property, BOOL *stop);
|
||||||
|
|
||||||
|
/** 将属性名换为其他key去字典中取值 */
|
||||||
|
typedef NSDictionary * (^MJReplacedKeyFromPropertyName)(void);
|
||||||
|
typedef id (^MJReplacedKeyFromPropertyName121)(NSString *propertyName);
|
||||||
|
/** 数组中需要转换的模型类 */
|
||||||
|
typedef NSDictionary * (^MJObjectClassInArray)(void);
|
||||||
|
/** 用于过滤字典中的值 */
|
||||||
|
typedef id (^MJNewValueFromOldValue)(id object, id oldValue, MJProperty *property);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成员属性相关的扩展
|
||||||
|
*/
|
||||||
|
@interface NSObject (MJProperty)
|
||||||
|
#pragma mark - 遍历
|
||||||
|
/**
|
||||||
|
* 遍历所有的成员
|
||||||
|
*/
|
||||||
|
+ (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration;
|
||||||
|
|
||||||
|
#pragma mark - 新值配置
|
||||||
|
/**
|
||||||
|
* 用于过滤字典中的值
|
||||||
|
*
|
||||||
|
* @param newValueFormOldValue 用于过滤字典中的值
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue;
|
||||||
|
+ (id)mj_getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property;
|
||||||
|
|
||||||
|
#pragma mark - key配置
|
||||||
|
/**
|
||||||
|
* 将属性名换为其他key去字典中取值
|
||||||
|
*
|
||||||
|
* @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName;
|
||||||
|
/**
|
||||||
|
* 将属性名换为其他key去字典中取值
|
||||||
|
*
|
||||||
|
* @param replacedKeyFromPropertyName121 将属性名换为其他key去字典中取值
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121;
|
||||||
|
|
||||||
|
#pragma mark - array model class配置
|
||||||
|
/**
|
||||||
|
* 数组中需要转换的模型类
|
||||||
|
*
|
||||||
|
* @param objectClassInArray 数组中需要转换的模型类
|
||||||
|
*/
|
||||||
|
+ (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray;
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,240 @@
|
||||||
|
//
|
||||||
|
// NSObject+MJProperty.m
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/4/17.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSObject+MJProperty.h"
|
||||||
|
#import "NSObject+MJKeyValue.h"
|
||||||
|
#import "NSObject+MJCoding.h"
|
||||||
|
#import "NSObject+MJClass.h"
|
||||||
|
#import "MJProperty.h"
|
||||||
|
#import "MJFoundation.h"
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||||
|
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||||
|
|
||||||
|
static const char MJReplacedKeyFromPropertyNameKey = '\0';
|
||||||
|
static const char MJReplacedKeyFromPropertyName121Key = '\0';
|
||||||
|
static const char MJNewValueFromOldValueKey = '\0';
|
||||||
|
static const char MJObjectClassInArrayKey = '\0';
|
||||||
|
|
||||||
|
static const char MJCachedPropertiesKey = '\0';
|
||||||
|
|
||||||
|
dispatch_semaphore_t mje_signalSemaphore;
|
||||||
|
dispatch_once_t mje_onceTokenSemaphore;
|
||||||
|
|
||||||
|
@implementation NSObject (Property)
|
||||||
|
|
||||||
|
+ (NSMutableDictionary *)mj_propertyDictForKey:(const void *)key
|
||||||
|
{
|
||||||
|
static NSMutableDictionary *replacedKeyFromPropertyNameDict;
|
||||||
|
static NSMutableDictionary *replacedKeyFromPropertyName121Dict;
|
||||||
|
static NSMutableDictionary *newValueFromOldValueDict;
|
||||||
|
static NSMutableDictionary *objectClassInArrayDict;
|
||||||
|
static NSMutableDictionary *cachedPropertiesDict;
|
||||||
|
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
replacedKeyFromPropertyNameDict = [NSMutableDictionary dictionary];
|
||||||
|
replacedKeyFromPropertyName121Dict = [NSMutableDictionary dictionary];
|
||||||
|
newValueFromOldValueDict = [NSMutableDictionary dictionary];
|
||||||
|
objectClassInArrayDict = [NSMutableDictionary dictionary];
|
||||||
|
cachedPropertiesDict = [NSMutableDictionary dictionary];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (key == &MJReplacedKeyFromPropertyNameKey) return replacedKeyFromPropertyNameDict;
|
||||||
|
if (key == &MJReplacedKeyFromPropertyName121Key) return replacedKeyFromPropertyName121Dict;
|
||||||
|
if (key == &MJNewValueFromOldValueKey) return newValueFromOldValueDict;
|
||||||
|
if (key == &MJObjectClassInArrayKey) return objectClassInArrayDict;
|
||||||
|
if (key == &MJCachedPropertiesKey) return cachedPropertiesDict;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - --私有方法--
|
||||||
|
+ (id)mj_propertyKey:(NSString *)propertyName
|
||||||
|
{
|
||||||
|
MJExtensionAssertParamNotNil2(propertyName, nil);
|
||||||
|
|
||||||
|
__block id key = nil;
|
||||||
|
// 查看有没有需要替换的key
|
||||||
|
if ([self respondsToSelector:@selector(mj_replacedKeyFromPropertyName121:)]) {
|
||||||
|
key = [self mj_replacedKeyFromPropertyName121:propertyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用block
|
||||||
|
if (!key) {
|
||||||
|
[self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
MJReplacedKeyFromPropertyName121 block = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyName121Key);
|
||||||
|
if (block) {
|
||||||
|
key = block(propertyName);
|
||||||
|
}
|
||||||
|
if (key) *stop = YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看有没有需要替换的key
|
||||||
|
if ((!key || [key isEqual:propertyName]) && [self respondsToSelector:@selector(mj_replacedKeyFromPropertyName)]) {
|
||||||
|
key = [self mj_replacedKeyFromPropertyName][propertyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!key || [key isEqual:propertyName]) {
|
||||||
|
[self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
NSDictionary *dict = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyNameKey);
|
||||||
|
if (dict) {
|
||||||
|
key = dict[propertyName];
|
||||||
|
}
|
||||||
|
if (key && ![key isEqual:propertyName]) *stop = YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.用属性名作为key
|
||||||
|
if (!key) key = propertyName;
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (Class)mj_propertyObjectClassInArray:(NSString *)propertyName
|
||||||
|
{
|
||||||
|
__block id clazz = nil;
|
||||||
|
if ([self respondsToSelector:@selector(mj_objectClassInArray)]) {
|
||||||
|
clazz = [self mj_objectClassInArray][propertyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clazz) {
|
||||||
|
[self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
NSDictionary *dict = objc_getAssociatedObject(c, &MJObjectClassInArrayKey);
|
||||||
|
if (dict) {
|
||||||
|
clazz = dict[propertyName];
|
||||||
|
}
|
||||||
|
if (clazz) *stop = YES;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是NSString类型
|
||||||
|
if ([clazz isKindOfClass:[NSString class]]) {
|
||||||
|
clazz = NSClassFromString(clazz);
|
||||||
|
}
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - --公共方法--
|
||||||
|
+ (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration
|
||||||
|
{
|
||||||
|
// 获得成员变量
|
||||||
|
NSArray *cachedProperties = [self mj_properties];
|
||||||
|
// 遍历成员变量
|
||||||
|
BOOL stop = NO;
|
||||||
|
for (MJProperty *property in cachedProperties) {
|
||||||
|
enumeration(property, &stop);
|
||||||
|
if (stop) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 公共方法
|
||||||
|
+ (NSArray *)mj_properties
|
||||||
|
{
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
NSMutableDictionary *cachedInfo = [self mj_propertyDictForKey:&MJCachedPropertiesKey];
|
||||||
|
NSMutableArray *cachedProperties = cachedInfo[NSStringFromClass(self)];
|
||||||
|
if (cachedProperties == nil) {
|
||||||
|
cachedProperties = [NSMutableArray array];
|
||||||
|
|
||||||
|
[self mj_enumerateClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
// 1.获得所有的成员变量
|
||||||
|
unsigned int outCount = 0;
|
||||||
|
objc_property_t *properties = class_copyPropertyList(c, &outCount);
|
||||||
|
|
||||||
|
// 2.遍历每一个成员变量
|
||||||
|
for (unsigned int i = 0; i<outCount; i++) {
|
||||||
|
MJProperty *property = [MJProperty cachedPropertyWithProperty:properties[i]];
|
||||||
|
// 过滤掉Foundation框架类里面的属性
|
||||||
|
if ([MJFoundation isClassFromFoundation:property.srcClass]) continue;
|
||||||
|
// 过滤掉`hash`, `superclass`, `description`, `debugDescription`
|
||||||
|
if ([MJFoundation isFromNSObjectProtocolProperty:property.name]) continue;
|
||||||
|
|
||||||
|
property.srcClass = c;
|
||||||
|
[property setOriginKey:[self mj_propertyKey:property.name] forClass:self];
|
||||||
|
[property setObjectClassInArray:[self mj_propertyObjectClassInArray:property.name] forClass:self];
|
||||||
|
[cachedProperties addObject:property];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.释放内存
|
||||||
|
free(properties);
|
||||||
|
}];
|
||||||
|
|
||||||
|
cachedInfo[NSStringFromClass(self)] = cachedProperties;
|
||||||
|
}
|
||||||
|
NSArray *properties = [cachedProperties copy];
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 新值配置
|
||||||
|
+ (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue {
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
objc_setAssociatedObject(self, &MJNewValueFromOldValueKey, newValueFormOldValue, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id)mj_getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(MJProperty *__unsafe_unretained)property{
|
||||||
|
// 如果有实现方法
|
||||||
|
if ([object respondsToSelector:@selector(mj_newValueFromOldValue:property:)]) {
|
||||||
|
return [object mj_newValueFromOldValue:oldValue property:property];
|
||||||
|
}
|
||||||
|
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
// 查看静态设置
|
||||||
|
__block id newValue = oldValue;
|
||||||
|
[self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) {
|
||||||
|
MJNewValueFromOldValue block = objc_getAssociatedObject(c, &MJNewValueFromOldValueKey);
|
||||||
|
if (block) {
|
||||||
|
newValue = block(object, oldValue, property);
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)mj_removeCachedProperties {
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
[[self mj_propertyDictForKey:&MJCachedPropertiesKey] removeAllObjects];
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - array model class配置
|
||||||
|
+ (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray
|
||||||
|
{
|
||||||
|
[self mj_setupBlockReturnValue:objectClassInArray key:&MJObjectClassInArrayKey];
|
||||||
|
|
||||||
|
[self mj_removeCachedProperties];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - key配置
|
||||||
|
|
||||||
|
+ (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName {
|
||||||
|
[self mj_setupBlockReturnValue:replacedKeyFromPropertyName key:&MJReplacedKeyFromPropertyNameKey];
|
||||||
|
|
||||||
|
[self mj_removeCachedProperties];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121 {
|
||||||
|
MJExtensionSemaphoreCreate
|
||||||
|
MJ_LOCK(mje_signalSemaphore);
|
||||||
|
objc_setAssociatedObject(self, &MJReplacedKeyFromPropertyName121Key, replacedKeyFromPropertyName121, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||||
|
|
||||||
|
[[self mj_propertyDictForKey:&MJCachedPropertiesKey] removeAllObjects];
|
||||||
|
MJ_UNLOCK(mje_signalSemaphore);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
// NSString+MJExtension.h
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/6/7.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "MJExtensionConst.h"
|
||||||
|
|
||||||
|
@interface NSString (MJExtension)
|
||||||
|
/**
|
||||||
|
* 驼峰转下划线(loveYou -> love_you)
|
||||||
|
*/
|
||||||
|
- (NSString *)mj_underlineFromCamel;
|
||||||
|
/**
|
||||||
|
* 下划线转驼峰(love_you -> loveYou)
|
||||||
|
*/
|
||||||
|
- (NSString *)mj_camelFromUnderline;
|
||||||
|
/**
|
||||||
|
* 首字母变大写
|
||||||
|
*/
|
||||||
|
- (NSString *)mj_firstCharUpper;
|
||||||
|
/**
|
||||||
|
* 首字母变小写
|
||||||
|
*/
|
||||||
|
- (NSString *)mj_firstCharLower;
|
||||||
|
|
||||||
|
- (BOOL)mj_isPureInt;
|
||||||
|
|
||||||
|
- (NSURL *)mj_url;
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
//
|
||||||
|
// NSString+MJExtension.m
|
||||||
|
// MJExtensionExample
|
||||||
|
//
|
||||||
|
// Created by MJ Lee on 15/6/7.
|
||||||
|
// Copyright (c) 2015年 小码哥. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSString+MJExtension.h"
|
||||||
|
|
||||||
|
@implementation NSString (MJExtension)
|
||||||
|
- (NSString *)mj_underlineFromCamel
|
||||||
|
{
|
||||||
|
if (self.length == 0) return self;
|
||||||
|
NSMutableString *string = [NSMutableString string];
|
||||||
|
for (NSUInteger i = 0; i<self.length; i++) {
|
||||||
|
unichar c = [self characterAtIndex:i];
|
||||||
|
NSString *cString = [NSString stringWithFormat:@"%c", c];
|
||||||
|
NSString *cStringLower = [cString lowercaseString];
|
||||||
|
if ([cString isEqualToString:cStringLower]) {
|
||||||
|
[string appendString:cStringLower];
|
||||||
|
} else {
|
||||||
|
[string appendString:@"_"];
|
||||||
|
[string appendString:cStringLower];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)mj_camelFromUnderline
|
||||||
|
{
|
||||||
|
if (self.length == 0) return self;
|
||||||
|
NSMutableString *string = [NSMutableString string];
|
||||||
|
NSArray *cmps = [self componentsSeparatedByString:@"_"];
|
||||||
|
for (NSUInteger i = 0; i<cmps.count; i++) {
|
||||||
|
NSString *cmp = cmps[i];
|
||||||
|
if (i && cmp.length) {
|
||||||
|
[string appendString:[NSString stringWithFormat:@"%c", [cmp characterAtIndex:0]].uppercaseString];
|
||||||
|
if (cmp.length >= 2) [string appendString:[cmp substringFromIndex:1]];
|
||||||
|
} else {
|
||||||
|
[string appendString:cmp];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)mj_firstCharLower
|
||||||
|
{
|
||||||
|
if (self.length == 0) return self;
|
||||||
|
NSMutableString *string = [NSMutableString string];
|
||||||
|
[string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].lowercaseString];
|
||||||
|
if (self.length >= 2) [string appendString:[self substringFromIndex:1]];
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)mj_firstCharUpper
|
||||||
|
{
|
||||||
|
if (self.length == 0) return self;
|
||||||
|
NSMutableString *string = [NSMutableString string];
|
||||||
|
[string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].uppercaseString];
|
||||||
|
if (self.length >= 2) [string appendString:[self substringFromIndex:1]];
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)mj_isPureInt
|
||||||
|
{
|
||||||
|
NSScanner *scan = [NSScanner scannerWithString:self];
|
||||||
|
int val;
|
||||||
|
return [scan scanInt:&val] && [scan isAtEnd];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURL *)mj_url
|
||||||
|
{
|
||||||
|
// [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"!$&'()*+,-./:;=?@_~%#[]"]];
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
|
||||||
|
return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyTracking</key>
|
||||||
|
<false/>
|
||||||
|
<key>NSPrivacyTrackingDomains</key>
|
||||||
|
<array/>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array/>
|
||||||
|
<key>NSPrivacyCollectedDataTypes</key>
|
||||||
|
<array/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
@ -0,0 +1,637 @@
|
||||||
|
MJExtension
|
||||||
|
===
|
||||||
|
[](https://github.com/apple/swift-package-manager)
|
||||||
|
[](https://github.com/Carthage/Carthage)
|
||||||
|
[](https://cocoapods.org/pods/MJExtension)
|
||||||
|

|
||||||
|
|
||||||
|
- A fast, convenient and nonintrusive conversion framework between JSON and model.
|
||||||
|
- 转换速度快、使用简单方便的字典转模型框架
|
||||||
|
|
||||||
|
[📜✍🏻**Release Notes**: more details](https://github.com/CoderMJLee/MJExtension/releases)
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
* [Getting Started 【开始使用】](#Getting_Started)
|
||||||
|
* [Features 【能做什么】](#Features)
|
||||||
|
* [Installation 【安装】](#Installation)
|
||||||
|
* [Examples 【示例】](#Examples)
|
||||||
|
* [Usage in Swift](#usage_in_swift)
|
||||||
|
* [JSON -> Model](#JSON_Model)
|
||||||
|
* [JSONString -> Model](#JSONString_Model)
|
||||||
|
* [Model contains model](#Model_contains_model)
|
||||||
|
* [Model contains model-array](#Model_contains_model_array)
|
||||||
|
* [Model name - JSON key mapping](#Model_name_JSON_key_mapping)
|
||||||
|
* [JSON array -> model array](#JSON_array_model_array)
|
||||||
|
* [Model -> JSON](#Model_JSON)
|
||||||
|
* [Model array -> JSON array](#Model_array_JSON_array)
|
||||||
|
* [Core Data](#Core_Data)
|
||||||
|
* [Coding](#Coding)
|
||||||
|
* [Secure Coding](#SecureCoding)
|
||||||
|
* [Camel -> underline](#Camel_underline)
|
||||||
|
* [NSString -> NSDate, nil -> @""](#NSString_NSDate)
|
||||||
|
* [NSDate -> NSString](#NSDate_NSString)
|
||||||
|
* [More use cases](#More_use_cases)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## <a id="Getting_Started"></a> Getting Started【开始使用】
|
||||||
|
|
||||||
|
### <a id="Features"></a> Features【能做什么】
|
||||||
|
- MJExtension是一套字典和模型之间互相转换的超轻量级框架
|
||||||
|
* `JSON` --> `Model`、`Core Data Model`
|
||||||
|
* `JSONString` --> `Model`、`Core Data Model`
|
||||||
|
* `Model`、`Core Data Model` --> `JSON`
|
||||||
|
* `JSON Array` --> `Model Array`、`Core Data Model Array`
|
||||||
|
* `JSONString` --> `Model Array`、`Core Data Model Array`
|
||||||
|
* `Model Array`、`Core Data Model Array` --> `JSON Array`
|
||||||
|
* Coding all properties of a model with only one line of code.
|
||||||
|
* 只需要一行代码,就能实现模型的所有属性进行Coding / SecureCoding(归档和解档)
|
||||||
|
|
||||||
|
### <a id="Installation"></a> Installation【安装】
|
||||||
|
|
||||||
|
#### CocoaPods【使用CocoaPods】
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
pod 'MJExtension'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Carthage
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
github "CoderMJLee/MJExtension"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Swift Package Manager
|
||||||
|
|
||||||
|
Released from [`3.4.0`](https://github.com/CoderMJLee/MJExtension/releases/)
|
||||||
|
|
||||||
|
#### Manually【手动导入】
|
||||||
|
|
||||||
|
- Drag all source files under folder `MJExtension` to your project.【将`MJExtension`文件夹中的所有源代码拽入项目中】
|
||||||
|
- Import the main header file:`#import "MJExtension.h"`【导入主头文件:`#import "MJExtension.h"`】
|
||||||
|
|
||||||
|
## <a id="Examples"></a> Examples【示例】
|
||||||
|
|
||||||
|
**Add `MJKeyValue` protocol to your model if needed【如果有需要, 请在模型中加入 `MJKeyValue` 协议】**
|
||||||
|
|
||||||
|
### <a id="usage_in_swift"></a> Usage in Swift [关于在Swift中使用MJExtension] ‼️
|
||||||
|
|
||||||
|
> Example:
|
||||||
|
>
|
||||||
|
> - [Model - MJTester.swift](MJExtensionTests/SwiftModel/MJTester.swift)
|
||||||
|
>
|
||||||
|
> - [Usage - SwiftModelTests.swift](MJExtensionTests/SwiftModelTests.swift)
|
||||||
|
|
||||||
|
```swift
|
||||||
|
@objc(MJTester)
|
||||||
|
@objcMembers
|
||||||
|
class MJTester: NSObject {
|
||||||
|
// make sure to use `dynamic` attribute for basic type & must use as Non-Optional & must set initial value
|
||||||
|
dynamic var isSpecialAgent: Bool = false
|
||||||
|
dynamic var age: Int = 0
|
||||||
|
|
||||||
|
var name: String?
|
||||||
|
var identifier: String?
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. `@objc` or `@objcMembers` attributes should be added to class or property for declaration of Objc accessibility [在 Swift4 之后, 请在属性前加 `@objc` 修饰或在类前增加 `@objcMembers`. 以保证 Swift 的属性能够暴露给 Objc 使用. ]
|
||||||
|
2. If you let `Bool` & `Int` as property type, make sure that using `dynamic` to attribute it. It must be `Non-Optional` type and assign `a default value`.[如果要使用 `Bool` 和 `Int` 等 Swfit 专用基本类型, 请使用 `dynamic` 关键字修饰, 类型为 `Non-Optional`, 並且给定初始值.]
|
||||||
|
|
||||||
|
> 纯Swift版的JSON与Model转换框架已经开源上架
|
||||||
|
>
|
||||||
|
> - [KakaJSON](https://github.com/kakaopensource/KakaJSON)
|
||||||
|
> - [中文教程](https://www.cnblogs.com/mjios/p/11352776.html)
|
||||||
|
> - 如果你的项目是用Swift写的Model,墙裂推荐使用[KakaJSON](https://github.com/kakaopensource/KakaJSON)
|
||||||
|
> - 已经对各种常用的数据场景进行了大量的单元测试
|
||||||
|
> - 简单易用、功能丰富、转换快速
|
||||||
|
|
||||||
|
### <a id="JSON_Model"></a> The most simple JSON -> Model【最简单的字典转模型】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
typedef enum {
|
||||||
|
SexMale,
|
||||||
|
SexFemale
|
||||||
|
} Sex;
|
||||||
|
|
||||||
|
@interface User : NSObject
|
||||||
|
@property (copy, nonatomic) NSString *name;
|
||||||
|
@property (copy, nonatomic) NSString *icon;
|
||||||
|
@property (assign, nonatomic) unsigned int age;
|
||||||
|
@property (copy, nonatomic) NSString *height;
|
||||||
|
@property (strong, nonatomic) NSNumber *money;
|
||||||
|
@property (assign, nonatomic) Sex sex;
|
||||||
|
@property (assign, nonatomic, getter=isGay) BOOL gay;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"name" : @"Jack",
|
||||||
|
@"icon" : @"lufy.png",
|
||||||
|
@"age" : @20,
|
||||||
|
@"height" : @"1.55",
|
||||||
|
@"money" : @100.9,
|
||||||
|
@"sex" : @(SexFemale),
|
||||||
|
@"gay" : @"true"
|
||||||
|
// @"gay" : @"1"
|
||||||
|
// @"gay" : @"NO"
|
||||||
|
};
|
||||||
|
|
||||||
|
// JSON -> User
|
||||||
|
User *user = [User mj_objectWithKeyValues:dict];
|
||||||
|
|
||||||
|
NSLog(@"name=%@, icon=%@, age=%zd, height=%@, money=%@, sex=%d, gay=%d", user.name, user.icon, user.age, user.height, user.money, user.sex, user.gay);
|
||||||
|
// name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="JSONString_Model"></a> JSONString -> Model【JSON字符串转模型】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
// 1.Define a JSONString
|
||||||
|
NSString *jsonString = @"{\"name\":\"Jack\", \"icon\":\"lufy.png\", \"age\":20}";
|
||||||
|
|
||||||
|
// 2.JSONString -> User
|
||||||
|
User *user = [User mj_objectWithKeyValues:jsonString];
|
||||||
|
|
||||||
|
// 3.Print user's properties
|
||||||
|
NSLog(@"name=%@, icon=%@, age=%d", user.name, user.icon, user.age);
|
||||||
|
// name=Jack, icon=lufy.png, age=20
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Model_contains_model"></a> Model contains model【模型中嵌套模型】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
@interface Status : NSObject
|
||||||
|
@property (copy, nonatomic) NSString *text;
|
||||||
|
@property (strong, nonatomic) User *user;
|
||||||
|
@property (strong, nonatomic) Status *retweetedStatus;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"text" : @"Agree!Nice weather!",
|
||||||
|
@"user" : @{
|
||||||
|
@"name" : @"Jack",
|
||||||
|
@"icon" : @"lufy.png"
|
||||||
|
},
|
||||||
|
@"retweetedStatus" : @{
|
||||||
|
@"text" : @"Nice weather!",
|
||||||
|
@"user" : @{
|
||||||
|
@"name" : @"Rose",
|
||||||
|
@"icon" : @"nami.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// JSON -> Status
|
||||||
|
Status *status = [Status mj_objectWithKeyValues:dict];
|
||||||
|
|
||||||
|
NSString *text = status.text;
|
||||||
|
NSString *name = status.user.name;
|
||||||
|
NSString *icon = status.user.icon;
|
||||||
|
NSLog(@"text=%@, name=%@, icon=%@", text, name, icon);
|
||||||
|
// text=Agree!Nice weather!, name=Jack, icon=lufy.png
|
||||||
|
|
||||||
|
NSString *text2 = status.retweetedStatus.text;
|
||||||
|
NSString *name2 = status.retweetedStatus.user.name;
|
||||||
|
NSString *icon2 = status.retweetedStatus.user.icon;
|
||||||
|
NSLog(@"text2=%@, name2=%@, icon2=%@", text2, name2, icon2);
|
||||||
|
// text2=Nice weather!, name2=Rose, icon2=nami.png
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Model_contains_model_array"></a> Model contains model-array【模型中有个数组属性,数组里面又要装着其他模型】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
@interface Ad : NSObject
|
||||||
|
@property (copy, nonatomic) NSString *image;
|
||||||
|
@property (copy, nonatomic) NSString *url;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface StatusResult : NSObject
|
||||||
|
/** Contatins status model */
|
||||||
|
@property (strong, nonatomic) NSMutableArray *statuses;
|
||||||
|
/** Contatins ad model */
|
||||||
|
@property (strong, nonatomic) NSArray *ads;
|
||||||
|
@property (strong, nonatomic) NSNumber *totalNumber;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
|
||||||
|
// Tell MJExtension what type of model will be contained in statuses and ads.
|
||||||
|
[StatusResult mj_setupObjectClassInArray:^NSDictionary *{
|
||||||
|
return @{
|
||||||
|
@"statuses" : @"Status",
|
||||||
|
// @"statuses" : [Status class],
|
||||||
|
@"ads" : @"Ad"
|
||||||
|
// @"ads" : [Ad class]
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
// Equals: StatusResult.m implements +mj_objectClassInArray method.
|
||||||
|
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"statuses" : @[
|
||||||
|
@{
|
||||||
|
@"text" : @"Nice weather!",
|
||||||
|
@"user" : @{
|
||||||
|
@"name" : @"Rose",
|
||||||
|
@"icon" : @"nami.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
@"text" : @"Go camping tomorrow!",
|
||||||
|
@"user" : @{
|
||||||
|
@"name" : @"Jack",
|
||||||
|
@"icon" : @"lufy.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
@"ads" : @[
|
||||||
|
@{
|
||||||
|
@"image" : @"ad01.png",
|
||||||
|
@"url" : @"http://www.ad01.com"
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
@"image" : @"ad02.png",
|
||||||
|
@"url" : @"http://www.ad02.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
@"totalNumber" : @"2014"
|
||||||
|
};
|
||||||
|
|
||||||
|
// JSON -> StatusResult
|
||||||
|
StatusResult *result = [StatusResult mj_objectWithKeyValues:dict];
|
||||||
|
|
||||||
|
NSLog(@"totalNumber=%@", result.totalNumber);
|
||||||
|
// totalNumber=2014
|
||||||
|
|
||||||
|
// Printing
|
||||||
|
for (Status *status in result.statuses) {
|
||||||
|
NSString *text = status.text;
|
||||||
|
NSString *name = status.user.name;
|
||||||
|
NSString *icon = status.user.icon;
|
||||||
|
NSLog(@"text=%@, name=%@, icon=%@", text, name, icon);
|
||||||
|
}
|
||||||
|
// text=Nice weather!, name=Rose, icon=nami.png
|
||||||
|
// text=Go camping tomorrow!, name=Jack, icon=lufy.png
|
||||||
|
|
||||||
|
// Printing
|
||||||
|
for (Ad *ad in result.ads) {
|
||||||
|
NSLog(@"image=%@, url=%@", ad.image, ad.url);
|
||||||
|
}
|
||||||
|
// image=ad01.png, url=http://www.ad01.com
|
||||||
|
// image=ad02.png, url=http://www.ad02.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Model_name_JSON_key_mapping"></a> Model name - JSON key mapping【模型中的属性名和字典中的key不相同(或者需要多级映射)】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
@interface Bag : NSObject
|
||||||
|
@property (copy, nonatomic) NSString *name;
|
||||||
|
@property (assign, nonatomic) double price;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface Student : NSObject
|
||||||
|
@property (copy, nonatomic) NSString *ID;
|
||||||
|
@property (copy, nonatomic) NSString *desc;
|
||||||
|
@property (copy, nonatomic) NSString *nowName;
|
||||||
|
@property (copy, nonatomic) NSString *oldName;
|
||||||
|
@property (copy, nonatomic) NSString *nameChangedTime;
|
||||||
|
@property (strong, nonatomic) Bag *bag;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
|
||||||
|
// How to map
|
||||||
|
[Student mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
|
||||||
|
return @{
|
||||||
|
@"ID" : @"id",
|
||||||
|
@"desc" : @"description",
|
||||||
|
@"oldName" : @"name.oldName",
|
||||||
|
@"nowName" : @"name.newName",
|
||||||
|
@"nameChangedTime" : @"name.info[1].nameChangedTime",
|
||||||
|
@"bag" : @"other.bag"
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
// Equals: Student.m implements +mj_replacedKeyFromPropertyName method.
|
||||||
|
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"id" : @"20",
|
||||||
|
@"description" : @"kids",
|
||||||
|
@"name" : @{
|
||||||
|
@"newName" : @"lufy",
|
||||||
|
@"oldName" : @"kitty",
|
||||||
|
@"info" : @[
|
||||||
|
@"test-data",
|
||||||
|
@{
|
||||||
|
@"nameChangedTime" : @"2013-08"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
@"other" : @{
|
||||||
|
@"bag" : @{
|
||||||
|
@"name" : @"a red bag",
|
||||||
|
@"price" : @100.7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// JSON -> Student
|
||||||
|
Student *stu = [Student mj_objectWithKeyValues:dict];
|
||||||
|
|
||||||
|
// Printing
|
||||||
|
NSLog(@"ID=%@, desc=%@, oldName=%@, nowName=%@, nameChangedTime=%@",
|
||||||
|
stu.ID, stu.desc, stu.oldName, stu.nowName, stu.nameChangedTime);
|
||||||
|
// ID=20, desc=kids, oldName=kitty, nowName=lufy, nameChangedTime=2013-08
|
||||||
|
NSLog(@"bagName=%@, bagPrice=%f", stu.bag.name, stu.bag.price);
|
||||||
|
// bagName=a red bag, bagPrice=100.700000
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <a id="JSON_array_model_array"></a> JSON array -> model array【将一个字典数组转成模型数组】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
NSArray *dictArray = @[
|
||||||
|
@{
|
||||||
|
@"name" : @"Jack",
|
||||||
|
@"icon" : @"lufy.png"
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
@"name" : @"Rose",
|
||||||
|
@"icon" : @"nami.png"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// JSON array -> User array
|
||||||
|
NSArray *userArray = [User mj_objectArrayWithKeyValuesArray:dictArray];
|
||||||
|
|
||||||
|
// Printing
|
||||||
|
for (User *user in userArray) {
|
||||||
|
NSLog(@"name=%@, icon=%@", user.name, user.icon);
|
||||||
|
}
|
||||||
|
// name=Jack, icon=lufy.png
|
||||||
|
// name=Rose, icon=nami.png
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Model_JSON"></a> Model -> JSON【将一个模型转成字典】
|
||||||
|
```objc
|
||||||
|
// New model
|
||||||
|
User *user = [[User alloc] init];
|
||||||
|
user.name = @"Jack";
|
||||||
|
user.icon = @"lufy.png";
|
||||||
|
|
||||||
|
Status *status = [[Status alloc] init];
|
||||||
|
status.user = user;
|
||||||
|
status.text = @"Nice mood!";
|
||||||
|
|
||||||
|
// Status -> JSON
|
||||||
|
NSDictionary *statusDict = status.mj_keyValues;
|
||||||
|
NSLog(@"%@", statusDict);
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
text = "Nice mood!";
|
||||||
|
user = {
|
||||||
|
icon = "lufy.png";
|
||||||
|
name = Jack;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// More complex situation
|
||||||
|
Student *stu = [[Student alloc] init];
|
||||||
|
stu.ID = @"123";
|
||||||
|
stu.oldName = @"rose";
|
||||||
|
stu.nowName = @"jack";
|
||||||
|
stu.desc = @"handsome";
|
||||||
|
stu.nameChangedTime = @"2018-09-08";
|
||||||
|
|
||||||
|
Bag *bag = [[Bag alloc] init];
|
||||||
|
bag.name = @"a red bag";
|
||||||
|
bag.price = 205;
|
||||||
|
stu.bag = bag;
|
||||||
|
|
||||||
|
NSDictionary *stuDict = stu.mj_keyValues;
|
||||||
|
NSLog(@"%@", stuDict);
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
ID = 123;
|
||||||
|
bag = {
|
||||||
|
name = "\U5c0f\U4e66\U5305";
|
||||||
|
price = 205;
|
||||||
|
};
|
||||||
|
desc = handsome;
|
||||||
|
nameChangedTime = "2018-09-08";
|
||||||
|
nowName = jack;
|
||||||
|
oldName = rose;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Model_array_JSON_array"></a> Model array -> JSON array【将一个模型数组转成字典数组】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
// New model array
|
||||||
|
User *user1 = [[User alloc] init];
|
||||||
|
user1.name = @"Jack";
|
||||||
|
user1.icon = @"lufy.png";
|
||||||
|
|
||||||
|
User *user2 = [[User alloc] init];
|
||||||
|
user2.name = @"Rose";
|
||||||
|
user2.icon = @"nami.png";
|
||||||
|
|
||||||
|
NSArray *userArray = @[user1, user2];
|
||||||
|
|
||||||
|
// Model array -> JSON array
|
||||||
|
NSArray *dictArray = [User mj_keyValuesArrayWithObjectArray:userArray];
|
||||||
|
NSLog(@"%@", dictArray);
|
||||||
|
/*
|
||||||
|
(
|
||||||
|
{
|
||||||
|
icon = "lufy.png";
|
||||||
|
name = Jack;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon = "nami.png";
|
||||||
|
name = Rose;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Core_Data"></a> Core Data
|
||||||
|
|
||||||
|
```swift
|
||||||
|
func json2CoreDataObject() {
|
||||||
|
context.performAndWait {
|
||||||
|
let object = MJCoreDataTester.mj_object(withKeyValues: Values.testJSONObject, context: context)
|
||||||
|
// use the object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func coreDataObject2JSON() {
|
||||||
|
context.performAndWait {
|
||||||
|
let dict = coreDataObject.mj_keyValues()
|
||||||
|
// use dict
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Coding"></a> Coding (Archive & Unarchive methods are deprecated in iOS 12)
|
||||||
|
|
||||||
|
```objc
|
||||||
|
#import "MJExtension.h"
|
||||||
|
|
||||||
|
@implementation MJBag
|
||||||
|
// NSCoding Implementation
|
||||||
|
MJCodingImplementation
|
||||||
|
@end
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
|
||||||
|
// what properties not to be coded
|
||||||
|
[MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{
|
||||||
|
return @[@"name"];
|
||||||
|
}];
|
||||||
|
// Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.
|
||||||
|
|
||||||
|
// Create model
|
||||||
|
MJBag *bag = [[MJBag alloc] init];
|
||||||
|
bag.name = @"Red bag";
|
||||||
|
bag.price = 200.8;
|
||||||
|
|
||||||
|
NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"];
|
||||||
|
// Encoding by archiving
|
||||||
|
[NSKeyedArchiver archiveRootObject:bag toFile:file];
|
||||||
|
|
||||||
|
// Decoding by unarchiving
|
||||||
|
MJBag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
|
||||||
|
NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
|
||||||
|
// name=(null), price=200.800000
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="SecureCoding"></a> Secure Coding
|
||||||
|
|
||||||
|
Using `MJSecureCodingImplementation(class, isSupport)` macro.
|
||||||
|
|
||||||
|
```objc
|
||||||
|
@import MJExtension;
|
||||||
|
|
||||||
|
// NSSecureCoding Implementation
|
||||||
|
MJSecureCodingImplementation(MJBag, YES)
|
||||||
|
|
||||||
|
@implementation MJBag
|
||||||
|
@end
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
|
||||||
|
// what properties not to be coded
|
||||||
|
[MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{
|
||||||
|
return @[@"name"];
|
||||||
|
}];
|
||||||
|
// Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.
|
||||||
|
|
||||||
|
// Create model
|
||||||
|
MJBag *bag = [[MJBag alloc] init];
|
||||||
|
bag.name = @"Red bag";
|
||||||
|
bag.price = 200.8;
|
||||||
|
bag.isBig = YES;
|
||||||
|
bag.weight = 200;
|
||||||
|
|
||||||
|
NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"bag.data"];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
// Encoding by archiving
|
||||||
|
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:bag requiringSecureCoding:YES error:&error];
|
||||||
|
[data writeToFile:file atomically:true];
|
||||||
|
|
||||||
|
// Decoding by unarchiving
|
||||||
|
NSData *readData = [NSFileManager.defaultManager contentsAtPath:file];
|
||||||
|
error = nil;
|
||||||
|
MJBag *decodedBag = [NSKeyedUnarchiver unarchivedObjectOfClass:MJBag.class fromData:readData error:&error];
|
||||||
|
MJExtensionLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="Camel_underline"></a> Camel -> underline【统一转换属性名(比如驼峰转下划线)】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
// Dog
|
||||||
|
#import "MJExtension.h"
|
||||||
|
|
||||||
|
@implementation Dog
|
||||||
|
+ (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName
|
||||||
|
{
|
||||||
|
// nickName -> nick_name
|
||||||
|
return [propertyName mj_underlineFromCamel];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
// NSDictionary
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"nick_name" : @"旺财",
|
||||||
|
@"sale_price" : @"10.5",
|
||||||
|
@"run_speed" : @"100.9"
|
||||||
|
};
|
||||||
|
// NSDictionary -> Dog
|
||||||
|
Dog *dog = [Dog mj_objectWithKeyValues:dict];
|
||||||
|
|
||||||
|
// printing
|
||||||
|
NSLog(@"nickName=%@, scalePrice=%f runSpeed=%f", dog.nickName, dog.salePrice, dog.runSpeed);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="NSString_NSDate"></a> NSString -> NSDate, nil -> @""【过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@"")】
|
||||||
|
```objc
|
||||||
|
// Book
|
||||||
|
#import "MJExtension.h"
|
||||||
|
|
||||||
|
@implementation Book
|
||||||
|
- (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property
|
||||||
|
{
|
||||||
|
if ([property.name isEqualToString:@"publisher"]) {
|
||||||
|
if (oldValue == nil) return @"";
|
||||||
|
} else if (property.type.typeClass == [NSDate class]) {
|
||||||
|
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
|
||||||
|
fmt.dateFormat = @"yyyy-MM-dd";
|
||||||
|
return [fmt dateFromString:oldValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
// NSDictionary
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"name" : @"5分钟突破iOS开发",
|
||||||
|
@"publishedTime" : @"2011-09-10"
|
||||||
|
};
|
||||||
|
// NSDictionary -> Book
|
||||||
|
Book *book = [Book mj_objectWithKeyValues:dict];
|
||||||
|
|
||||||
|
// printing
|
||||||
|
NSLog(@"name=%@, publisher=%@, publishedTime=%@", book.name, book.publisher, book.publishedTime);
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a id="NSDate_NSString"></a> NSDate -> NSString【模型转字典时, 修改 Date 类型至 String】
|
||||||
|
|
||||||
|
```objc
|
||||||
|
- (void)mj_objectDidConvertToKeyValues:(NSMutableDictionary *)keyValues {
|
||||||
|
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
||||||
|
// formatter.dateFormat = @"yyy-MM-dd";
|
||||||
|
// should use sharedFormatter for better performance
|
||||||
|
keyValues[@"publishedTime"] = [sharedFormatter stringFromDate:self.publishedTime];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### <a id="More_use_cases"></a> More use cases【更多用法】
|
||||||
|
|
||||||
|
- Please reference to `NSObject+MJKeyValue.h` and `NSObject+MJCoding.h`
|
||||||
|
|
||||||
|
|
||||||
|
## 期待
|
||||||
|
* 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的框架代码看看BUG修复没有)
|
||||||
|
* 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢
|
||||||
|
* 如果你想为MJExtension输出代码,请拼命Pull Requests我
|
||||||
|
|
||||||
|
|
@ -82,12 +82,44 @@ PODS:
|
||||||
- MarqueeLabel (4.5.3)
|
- MarqueeLabel (4.5.3)
|
||||||
- Masonry (1.1.0)
|
- Masonry (1.1.0)
|
||||||
- MBProgressHUD (1.2.0)
|
- MBProgressHUD (1.2.0)
|
||||||
|
- MJExtension (3.4.2)
|
||||||
- MJRefresh (3.7.9)
|
- MJRefresh (3.7.9)
|
||||||
- Moya (15.0.0):
|
- Moya (15.0.0):
|
||||||
- Moya/Core (= 15.0.0)
|
- Moya/Core (= 15.0.0)
|
||||||
- Moya/Core (15.0.0):
|
- Moya/Core (15.0.0):
|
||||||
- Alamofire (~> 5.0)
|
- Alamofire (~> 5.0)
|
||||||
- ObjectMapper (4.4.2)
|
- ObjectMapper (4.4.2)
|
||||||
|
- "OpenIMSDK (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- "OpenIMSDK/Callbacker (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/CallbackProxy (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/Interface (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/Model (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDK/Utils (= 3.8.3+hotfix.3.1)"
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Callbacker (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Model
|
||||||
|
- OpenIMSDK/Utils
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/CallbackProxy (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Utils
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Interface (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Callbacker
|
||||||
|
- OpenIMSDK/CallbackProxy
|
||||||
|
- OpenIMSDK/Model
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Model (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- OpenIMSDK/Utils
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDK/Utils (3.8.3+hotfix.3.1)":
|
||||||
|
- MJExtension
|
||||||
|
- "OpenIMSDKCore (= 3.8.3+3)"
|
||||||
|
- "OpenIMSDKCore (3.8.3+3)"
|
||||||
- Popover (1.3.0)
|
- Popover (1.3.0)
|
||||||
- RxCocoa (6.8.0):
|
- RxCocoa (6.8.0):
|
||||||
- RxRelay (= 6.8.0)
|
- RxRelay (= 6.8.0)
|
||||||
|
|
@ -138,6 +170,7 @@ DEPENDENCIES:
|
||||||
- MJRefresh
|
- MJRefresh
|
||||||
- Moya
|
- Moya
|
||||||
- ObjectMapper
|
- ObjectMapper
|
||||||
|
- OpenIMSDK
|
||||||
- Popover
|
- Popover
|
||||||
- RxCocoa
|
- RxCocoa
|
||||||
- RxDataSources
|
- RxDataSources
|
||||||
|
|
@ -179,9 +212,12 @@ SPEC REPOS:
|
||||||
- lottie-ios
|
- lottie-ios
|
||||||
- MarqueeLabel
|
- MarqueeLabel
|
||||||
- Masonry
|
- Masonry
|
||||||
|
- MJExtension
|
||||||
- MJRefresh
|
- MJRefresh
|
||||||
- Moya
|
- Moya
|
||||||
- ObjectMapper
|
- ObjectMapper
|
||||||
|
- OpenIMSDK
|
||||||
|
- OpenIMSDKCore
|
||||||
- Popover
|
- Popover
|
||||||
- RxCocoa
|
- RxCocoa
|
||||||
- RxDataSources
|
- RxDataSources
|
||||||
|
|
@ -235,9 +271,12 @@ SPEC CHECKSUMS:
|
||||||
MarqueeLabel: 0c57d4c6634e04a6d015af79f7c9a175b2309525
|
MarqueeLabel: 0c57d4c6634e04a6d015af79f7c9a175b2309525
|
||||||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||||
MBProgressHUD: 1b0fb447e80a0fda94808180750e8b78a07b3cd2
|
MBProgressHUD: 1b0fb447e80a0fda94808180750e8b78a07b3cd2
|
||||||
|
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||||
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
||||||
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
|
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
|
||||||
|
OpenIMSDK: c1880296ead605bcac2a289ad0aef9170fe6e6df
|
||||||
|
OpenIMSDKCore: 75caba22be8ee484011f367711178312bd64a17d
|
||||||
Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
|
Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
|
||||||
RxCocoa: 2d33c1e1e5d66492052ad46b11024ae287572880
|
RxCocoa: 2d33c1e1e5d66492052ad46b11024ae287572880
|
||||||
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
||||||
|
|
@ -256,6 +295,6 @@ SPEC CHECKSUMS:
|
||||||
URLNavigator: e9c0426ba6e6ac57f34d018bbf3df840797f984d
|
URLNavigator: e9c0426ba6e6ac57f34d018bbf3df840797f984d
|
||||||
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
|
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
|
||||||
|
|
||||||
PODFILE CHECKSUM: 7d3667576e8d6c3f1a98be0e406f215041cf2eb7
|
PODFILE CHECKSUM: d9389fd0d3da8895e9ddac8adbec655edaf9bb3d
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,661 @@
|
||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// CallbackProxy.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by Snow on 2021/6/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
@import OpenIMCore;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface CallbackProxy : NSObject <Open_im_sdk_callbackBase>
|
||||||
|
|
||||||
|
- (instancetype)initWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)dispatchMainThread:(void (NS_NOESCAPE ^)(void))todo;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
//
|
||||||
|
// CallbackProxy.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by Snow on 2021/6/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@interface CallbackProxy() {
|
||||||
|
OIMSuccessCallback _onSuccess;
|
||||||
|
OIMFailureCallback _onError;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CallbackProxy
|
||||||
|
|
||||||
|
- (instancetype)initWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
if (self = [super init]) {
|
||||||
|
_onSuccess = [onSuccess copy];
|
||||||
|
_onError = [onFailure copy];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onError:(int32_t)errCode errMsg:(NSString * _Nullable)errMsg {
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (_onError) {
|
||||||
|
_onError(errCode, errMsg);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onSuccess:(NSString * _Nullable)data {
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (_onSuccess) {
|
||||||
|
_onSuccess(data);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dispatchMainThread:(void (NS_NOESCAPE ^)(void))todo {
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
todo();
|
||||||
|
} else {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
todo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// SendMessageCallbackProxy.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by Snow on 2021/6/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@import OpenIMCore;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface SendMessageCallbackProxy : CallbackProxy <Open_im_sdk_callbackSendMsgCallBack>
|
||||||
|
|
||||||
|
- (instancetype)initWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onProgress:(OIMNumberCallback)onProgress
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
//
|
||||||
|
// SendMessageCallbackProxy.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by Snow on 2021/6/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SendMessageCallbackProxy.h"
|
||||||
|
|
||||||
|
@interface SendMessageCallbackProxy(){
|
||||||
|
OIMSuccessCallback _onSuccess;
|
||||||
|
OIMFailureCallback _onFailure;
|
||||||
|
OIMNumberCallback _onProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SendMessageCallbackProxy
|
||||||
|
|
||||||
|
- (instancetype)initWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onProgress:(OIMNumberCallback)onProgress
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
if (self = [super init]) {
|
||||||
|
_onSuccess = [onSuccess copy];
|
||||||
|
_onFailure = [onFailure copy];
|
||||||
|
_onProgress = [onProgress copy];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onError:(int32_t)errCode errMsg:(NSString * _Nullable)errMsg {
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (_onFailure) {
|
||||||
|
_onFailure(errCode, errMsg);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onProgress:(long)progress {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (_onProgress) {
|
||||||
|
_onProgress(progress);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onSuccess:(NSString * _Nullable)data {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (_onSuccess) {
|
||||||
|
_onSuccess(data);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// UploadFileCallbackProxy.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2023/6/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
@import OpenIMCore;
|
||||||
|
|
||||||
|
typedef void (^OIMUploadProgressCallback)(NSInteger saveBytes, NSInteger currentBytes, NSInteger totalBytes);
|
||||||
|
typedef void (^OIMUploadCompletionCallback)(NSInteger totalBytes, NSString * _Nonnull url, NSInteger putType);
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface UploadFileCallbackProxy : NSObject <Open_im_sdk_callbackUploadFileCallback>
|
||||||
|
|
||||||
|
- (instancetype)initWithOnProgress:(OIMUploadProgressCallback)progress
|
||||||
|
onCompletion:(OIMUploadCompletionCallback)completion;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface UploadLogsCallbackProxy : NSObject <Open_im_sdk_callbackUploadLogProgress>
|
||||||
|
|
||||||
|
- (instancetype)initWithOnProgress:(OIMUploadProgressCallback)progress;
|
||||||
|
|
||||||
|
@end
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
//
|
||||||
|
// UploadFileCallbackProxy.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2023/6/19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "UploadFileCallbackProxy.h"
|
||||||
|
|
||||||
|
@interface UploadFileCallbackProxy() {
|
||||||
|
OIMUploadProgressCallback onProgress;
|
||||||
|
OIMUploadCompletionCallback onCompletion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation UploadFileCallbackProxy
|
||||||
|
|
||||||
|
- (instancetype)initWithOnProgress:(OIMUploadProgressCallback)progress
|
||||||
|
onCompletion:(OIMUploadCompletionCallback)completion {
|
||||||
|
|
||||||
|
if (self = [super init]) {
|
||||||
|
onProgress = progress;
|
||||||
|
onCompletion = completion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dispatchMainThread:(void (NS_NOESCAPE ^)(void))todo {
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
todo();
|
||||||
|
} else {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
todo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)complete:(int64_t)size url:(NSString *)url typ:(long)typ {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
onCompletion(size, url, typ);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hashPartComplete:(NSString* _Nullable)partsHash fileHash:(NSString* _Nullable)fileHash {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hashPartProgress:(long)index size:(int64_t)size partHash:(NSString *)partHash {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)open:(int64_t)size {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)partSize:(int64_t)partSize num:(long)num {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadComplete:(int64_t)fileSize streamSize:(int64_t)streamSize storageSize:(int64_t)storageSize {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
onProgress(fileSize, streamSize, storageSize);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadID:(NSString* _Nullable)uploadID {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadPartComplete:(long)index partSize:(int64_t)partSize partHash:(NSString *)partHash {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface UploadLogsCallbackProxy() {
|
||||||
|
OIMUploadProgressCallback onProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation UploadLogsCallbackProxy
|
||||||
|
|
||||||
|
- (instancetype)initWithOnProgress:(OIMUploadProgressCallback)progress {
|
||||||
|
if (self = [super init]) {
|
||||||
|
onProgress = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onProgress:(int64_t)current size:(int64_t)size {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
onProgress(current, current, size);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dispatchMainThread:(void (NS_NOESCAPE ^)(void))todo {
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
todo();
|
||||||
|
} else {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
todo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
//
|
||||||
|
// OIMCallbacker+Closure.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/3/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMCallbacker.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMCallbacker (Closure)
|
||||||
|
/**
|
||||||
|
* Set conversation listeners
|
||||||
|
* If a conversation changes, it triggers onConversationChanged.
|
||||||
|
* If a new conversation is added, it triggers onNewConversation.
|
||||||
|
* If the total unread message count changes, it triggers onTotalUnreadMessageCountChanged.
|
||||||
|
*
|
||||||
|
* Actively fetch conversation records at app startup, and later refresh data based on listener callbacks for conversation changes.
|
||||||
|
*/
|
||||||
|
- (void)setConversationListenerWithOnSyncServerStart:(OIMBoolCallback)onSyncServerStart
|
||||||
|
onSyncServerFinish:(OIMBoolCallback)onSyncServerFinish
|
||||||
|
onSyncServerFailed:(OIMBoolCallback)onSyncServerFailed
|
||||||
|
onSyncServerProgress:(OIMNumberCallback)onSyncServerProgress
|
||||||
|
onConversationChanged:(OIMConversationsInfoCallback)onConversationChanged
|
||||||
|
onNewConversation:(OIMConversationsInfoCallback)onNewConversation
|
||||||
|
onTotalUnreadMessageCountChanged:(OIMNumberCallback)onTotalUnreadMessageCountChanged;
|
||||||
|
|
||||||
|
- (void)setConversationListenerWithOnSyncServerStart:(OIMBoolCallback)onSyncServerStart
|
||||||
|
onSyncServerFinish:(OIMBoolCallback)onSyncServerFinish
|
||||||
|
onSyncServerFailed:(OIMBoolCallback)onSyncServerFailed
|
||||||
|
onSyncServerProgress:(OIMNumberCallback)onSyncServerProgress
|
||||||
|
onConversationChanged:(OIMConversationsInfoCallback)onConversationChanged
|
||||||
|
onNewConversation:(OIMConversationsInfoCallback)onNewConversation
|
||||||
|
onTotalUnreadMessageCountChanged:(OIMNumberCallback)onTotalUnreadMessageCountChanged
|
||||||
|
onConversationUserInputStatusChanged:(nullable OIMInputStatusChangedCallback)onConversationUserInputStatusChanged;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set friend relationship listeners
|
||||||
|
*
|
||||||
|
* Callbacks for a friend being added to the blacklist (onBlackAdded),
|
||||||
|
* a friend being removed from the blacklist (onBlackDeleted),
|
||||||
|
* accepting a friend request initiated by someone (onFriendApplicationAccepted),
|
||||||
|
* receiving a friend request initiated by someone (onFriendApplicationAdded),
|
||||||
|
* deleting a friend request (onFriendApplicationDeleted),
|
||||||
|
* rejecting a friend request (onFriendApplicationRejected),
|
||||||
|
* friend profile changes (onFriendInfoChanged),
|
||||||
|
* added friends (onFriendAdded),
|
||||||
|
* and deleted friends (onFriendDeleted).
|
||||||
|
*/
|
||||||
|
- (void)setFriendListenerWithOnBlackAdded:(OIMBlackInfoCallback)onBlackAdded
|
||||||
|
onBlackDeleted:(OIMBlackInfoCallback)onBlackDeleted
|
||||||
|
onFriendApplicationAccepted:(OIMFriendApplicationCallback)onFriendApplicationAccepted
|
||||||
|
onFriendApplicationAdded:(OIMFriendApplicationCallback)onFriendApplicationAdded
|
||||||
|
onFriendApplicationDeleted:(OIMFriendApplicationCallback)onFriendApplicationDeleted
|
||||||
|
onFriendApplicationRejected:(OIMFriendApplicationCallback)onFriendApplicationRejected
|
||||||
|
onFriendInfoChanged:(OIMFriendInfoCallback)onFriendInfoChanged
|
||||||
|
onFriendAdded:(OIMFriendInfoCallback)onFriendAdded
|
||||||
|
onFriendDeleted:(OIMFriendInfoCallback)onFriendDeleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group listeners
|
||||||
|
*/
|
||||||
|
- (void)setGroupListenerWithOnGroupInfoChanged:(OIMGroupInfoCallback)onGroupInfoChanged
|
||||||
|
onJoinedGroupAdded:(OIMGroupInfoCallback)onJoinedGroupAdded
|
||||||
|
onJoinedGroupDeleted:(OIMGroupInfoCallback)onJoinedGroupDeleted
|
||||||
|
onGroupMemberAdded:(OIMGroupMemberInfoCallback)onGroupMemberAdded
|
||||||
|
onGroupMemberDeleted:(OIMGroupMemberInfoCallback)onGroupMemberDeleted
|
||||||
|
onGroupMemberInfoChanged:(OIMGroupMemberInfoCallback)onGroupMemberInfoChanged
|
||||||
|
onGroupApplicationAdded:(OIMGroupApplicationCallback)onGroupApplicationAdded
|
||||||
|
onGroupApplicationDeleted:(OIMGroupApplicationCallback)onGroupApplicationDeleted
|
||||||
|
onGroupApplicationAccepted:(OIMGroupApplicationCallback)onGroupApplicationAccepted
|
||||||
|
onGroupApplicationRejected:(OIMGroupApplicationCallback)onGroupApplicationRejected
|
||||||
|
onGroupDismissed:(nullable OIMGroupInfoCallback)onGroupDismissed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add message listeners
|
||||||
|
*
|
||||||
|
* When the other party revokes a message (onRecvMessageRevoked), use the callback to replace displayed messages with "xx revoked a message."
|
||||||
|
* When the other party reads a message (onRecvC2CReadReceipt), use the callback to change the status of read messages.
|
||||||
|
* For new messages (onRecvNewMessage), add messages to the interface.
|
||||||
|
*/
|
||||||
|
- (void)setAdvancedMsgListenerWithOnRecvMessageRevoked:(OIMRevokedCallback)onRecvMessageRevoked
|
||||||
|
onRecvC2CReadReceipt:(OIMReceiptCallback)onRecvC2CReadReceipt
|
||||||
|
onRecvGroupReadReceipt:(OIMReceiptCallback)onRecvGroupReadReceipt
|
||||||
|
onRecvNewMessage:(OIMMessageInfoCallback)onRecvNewMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User information listeners
|
||||||
|
*/
|
||||||
|
- (void)setSelfUserInfoUpdateListener:(OIMUserInfoCallback)onUserInfoUpdate;
|
||||||
|
|
||||||
|
- (void)setUserListenerWithUserInfoUpdate:(nullable OIMUserInfoCallback)onUserInfoUpdate
|
||||||
|
onUserStatusChanged:(nullable OIMUserStatusInfoCallback)onUserStatusChanged;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom messages
|
||||||
|
*/
|
||||||
|
- (void)setRecvCustomBusinessMessageListener:(OIMObjectCallback)onRecvCustomBusinessMessage;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
//
|
||||||
|
// OIMCallbacker+Closure.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/3/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMCallbacker+Closure.h"
|
||||||
|
|
||||||
|
@implementation OIMCallbacker (Closure)
|
||||||
|
|
||||||
|
- (void)setConversationListenerWithOnSyncServerStart:(OIMBoolCallback)onSyncServerStart
|
||||||
|
onSyncServerFinish:(OIMBoolCallback)onSyncServerFinish
|
||||||
|
onSyncServerFailed:(OIMBoolCallback)onSyncServerFailed
|
||||||
|
onSyncServerProgress:(OIMNumberCallback)onSyncServerProgress
|
||||||
|
onConversationChanged:(OIMConversationsInfoCallback)onConversationChanged onNewConversation:(OIMConversationsInfoCallback)onNewConversation onTotalUnreadMessageCountChanged:(OIMNumberCallback)onTotalUnreadMessageCountChanged {
|
||||||
|
[self setConversationListenerWithOnSyncServerStart:onSyncServerStart
|
||||||
|
onSyncServerFinish:onSyncServerFinish
|
||||||
|
onSyncServerFailed:onSyncServerFailed
|
||||||
|
onSyncServerProgress: onSyncServerProgress
|
||||||
|
onConversationChanged:onConversationChanged
|
||||||
|
onNewConversation:onNewConversation
|
||||||
|
onTotalUnreadMessageCountChanged:onTotalUnreadMessageCountChanged
|
||||||
|
onConversationUserInputStatusChanged:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversationListenerWithOnSyncServerStart:(OIMBoolCallback)onSyncServerStart
|
||||||
|
onSyncServerFinish:(OIMBoolCallback)onSyncServerFinish
|
||||||
|
onSyncServerFailed:(OIMBoolCallback)onSyncServerFailed
|
||||||
|
onSyncServerProgress:(OIMNumberCallback)onSyncServerProgress
|
||||||
|
onConversationChanged:(OIMConversationsInfoCallback)onConversationChanged onNewConversation:(OIMConversationsInfoCallback)onNewConversation onTotalUnreadMessageCountChanged:(OIMNumberCallback)onTotalUnreadMessageCountChanged onConversationUserInputStatusChanged:(OIMInputStatusChangedCallback)onConversationUserInputStatusChanged {
|
||||||
|
self.syncServerStart = onSyncServerStart;
|
||||||
|
self.syncServerFinish = onSyncServerFinish;
|
||||||
|
self.syncServerFailed = onSyncServerFailed;
|
||||||
|
self.syncServerProgress = onSyncServerProgress;
|
||||||
|
self.onConversationChanged = onConversationChanged;
|
||||||
|
self.onNewConversation = onNewConversation;
|
||||||
|
self.onTotalUnreadMessageCountChanged = onTotalUnreadMessageCountChanged;
|
||||||
|
self.onConversationUserInputStatusChanged = onConversationUserInputStatusChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setFriendListenerWithOnBlackAdded:(OIMBlackInfoCallback)onBlackAdded
|
||||||
|
onBlackDeleted:(OIMBlackInfoCallback)onBlackDeleted
|
||||||
|
onFriendApplicationAccepted:(OIMFriendApplicationCallback)onFriendApplicationAccepted
|
||||||
|
onFriendApplicationAdded:(OIMFriendApplicationCallback)onFriendApplicationAdded
|
||||||
|
onFriendApplicationDeleted:(OIMFriendApplicationCallback)onFriendApplicationDeleted
|
||||||
|
onFriendApplicationRejected:(OIMFriendApplicationCallback)onFriendApplicationRejected
|
||||||
|
onFriendInfoChanged:(OIMFriendInfoCallback)onFriendInfoChanged
|
||||||
|
onFriendAdded:(OIMFriendInfoCallback)onFriendAdded
|
||||||
|
onFriendDeleted:(OIMFriendInfoCallback)onFriendDeleted {
|
||||||
|
self.onBlackAdded = onBlackAdded;
|
||||||
|
self.onBlackDeleted = onBlackDeleted;
|
||||||
|
self.onFriendApplicationAccepted = onFriendApplicationAccepted;
|
||||||
|
self.onFriendApplicationAdded = onFriendApplicationAdded;
|
||||||
|
self.onFriendApplicationDeleted = onFriendApplicationDeleted;
|
||||||
|
self.onFriendApplicationRejected = onFriendApplicationRejected;
|
||||||
|
self.onFriendInfoChanged = onFriendInfoChanged;
|
||||||
|
self.onFriendAdded = onFriendAdded;
|
||||||
|
self.onFriendDeleted = onFriendDeleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupListenerWithOnGroupInfoChanged:(OIMGroupInfoCallback)onGroupInfoChanged
|
||||||
|
onJoinedGroupAdded:(OIMGroupInfoCallback)onJoinedGroupAdded
|
||||||
|
onJoinedGroupDeleted:(OIMGroupInfoCallback)onJoinedGroupDeleted
|
||||||
|
onGroupMemberAdded:(OIMGroupMemberInfoCallback)onGroupMemberAdded
|
||||||
|
onGroupMemberDeleted:(OIMGroupMemberInfoCallback)onGroupMemberDeleted
|
||||||
|
onGroupMemberInfoChanged:(OIMGroupMemberInfoCallback)onGroupMemberInfoChanged
|
||||||
|
onGroupApplicationAdded:(OIMGroupApplicationCallback)onGroupApplicationAdded
|
||||||
|
onGroupApplicationDeleted:(OIMGroupApplicationCallback)onGroupApplicationDeleted
|
||||||
|
onGroupApplicationAccepted:(OIMGroupApplicationCallback)onGroupApplicationAccepted
|
||||||
|
onGroupApplicationRejected:(OIMGroupApplicationCallback)onGroupApplicationRejected
|
||||||
|
onGroupDismissed:(OIMGroupInfoCallback)onGroupDismissed {
|
||||||
|
self.onGroupInfoChanged = onGroupInfoChanged;
|
||||||
|
self.onJoinedGroupAdded = onJoinedGroupAdded;
|
||||||
|
self.onJoinedGroupDeleted = onJoinedGroupDeleted;
|
||||||
|
self.onGroupMemberAdded = onGroupMemberAdded;
|
||||||
|
self.onGroupMemberInfoChanged = onGroupMemberInfoChanged;
|
||||||
|
self.onGroupApplicationAdded = onGroupApplicationAdded;
|
||||||
|
self.onGroupApplicationDeleted = onGroupApplicationDeleted;
|
||||||
|
self.onGroupApplicationAccepted = onGroupApplicationAccepted;
|
||||||
|
self.onGroupApplicationRejected = onGroupApplicationRejected;
|
||||||
|
self.onGroupDismissed = onGroupDismissed;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setAdvancedMsgListenerWithOnRecvMessageRevoked:(OIMRevokedCallback)onRecvMessageRevoked
|
||||||
|
onRecvC2CReadReceipt:(OIMReceiptCallback)onRecvC2CReadReceipt
|
||||||
|
onRecvGroupReadReceipt:(OIMReceiptCallback)onRecvGroupReadReceipt
|
||||||
|
onRecvNewMessage:(OIMMessageInfoCallback)onRecvNewMessage {
|
||||||
|
|
||||||
|
self.onRecvMessageRevoked = onRecvMessageRevoked;
|
||||||
|
self.onRecvC2CReadReceipt = onRecvC2CReadReceipt;
|
||||||
|
self.onRecvGroupReadReceipt = onRecvGroupReadReceipt;
|
||||||
|
self.onRecvNewMessage = onRecvNewMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSelfUserInfoUpdateListener:(OIMUserInfoCallback)onUserInfoUpdate {
|
||||||
|
[self setUserListenerWithUserInfoUpdate:onUserInfoUpdate onUserStatusChanged:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setUserListenerWithUserInfoUpdate:(OIMUserInfoCallback)onUserInfoUpdate
|
||||||
|
onUserStatusChanged:(OIMUserStatusInfoCallback)onUserStatusChanged {
|
||||||
|
self.onSelfInfoUpdated = onUserInfoUpdate;
|
||||||
|
self.onUserStatusChanged = onUserStatusChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setRecvCustomBusinessMessageListener:(OIMObjectCallback)onRecvCustomBusinessMessage {
|
||||||
|
self.onRecvCustomBusinessMessage = onRecvCustomBusinessMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,461 @@
|
||||||
|
//
|
||||||
|
// OIMCallbacker.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
#import "OIMUserInfo.h"
|
||||||
|
#import "OIMFullUserInfo.h"
|
||||||
|
#import "OIMFriendApplication.h"
|
||||||
|
#import "OIMGroupApplicationInfo.h"
|
||||||
|
#import "OIMGroupInfo.h"
|
||||||
|
#import "OIMGroupMemberInfo.h"
|
||||||
|
#import "OIMConversationInfo.h"
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
#import "OIMSearchParam.h"
|
||||||
|
#import "OIMSearchResultInfo.h"
|
||||||
|
#import "OIMSimpleResultInfo.h"
|
||||||
|
#import "OIMSimpleRequstInfo.h"
|
||||||
|
|
||||||
|
@import OpenIMCore;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (^OIMSimpleResultCallback)(OIMSimpleResultInfo * _Nullable result);
|
||||||
|
typedef void (^OIMSimpleResultsCallback)(NSArray <OIMSimpleResultInfo *> * _Nullable results);
|
||||||
|
|
||||||
|
typedef void (^OIMUserInfoCallback)(OIMUserInfo * _Nullable userInfo);
|
||||||
|
typedef void (^OIMUsersInfoCallback)(NSArray <OIMUserInfo *> * _Nullable usersInfo);
|
||||||
|
typedef void (^OIMUsersCallback)(NSArray <OIMPublicUserInfo *> * _Nullable userInfos);
|
||||||
|
typedef void (^OIMPublicUserInfoCallback)(OIMPublicUserInfo * _Nullable userInfo);
|
||||||
|
typedef void (^OIMPublicUsersInfoCallback)(NSArray <OIMPublicUserInfo *> * _Nullable userInfos);
|
||||||
|
typedef void (^OIMBlacksInfoCallback)(NSArray <OIMBlackInfo *> * _Nullable blackInfos);
|
||||||
|
typedef void (^OIMUserStatusInfoCallback)(OIMUserStatusInfo * _Nullable statusInfo);
|
||||||
|
typedef void (^OIMUserStatusInfosCallback)(NSArray <OIMUserStatusInfo *> * _Nullable statusInfos);
|
||||||
|
|
||||||
|
typedef void (^OIMFriendApplicationCallback)(OIMFriendApplication * _Nullable friendApplication);
|
||||||
|
typedef void (^OIMFriendApplicationsCallback)(NSArray <OIMFriendApplication *> * _Nullable friendApplications);
|
||||||
|
|
||||||
|
typedef void (^OIMFriendInfoCallback)(OIMFriendInfo * _Nullable friendInfo);
|
||||||
|
typedef void (^OIMFriendsInfoCallback)(NSArray<OIMFriendInfo *> * _Nullable friendInfo);
|
||||||
|
typedef void (^OIMBlackInfoCallback)(OIMBlackInfo * _Nullable blackInfo);
|
||||||
|
typedef void (^OIMBlacksInfoCallback)(NSArray<OIMBlackInfo *> * _Nullable blackInfo);
|
||||||
|
typedef void (^OIMSearchUsersInfoCallback)(NSArray<OIMSearchFriendsInfo *> * _Nullable usersInfo);
|
||||||
|
|
||||||
|
typedef void (^OIMGroupApplicationCallback)(OIMGroupApplicationInfo * _Nullable groupApplication);
|
||||||
|
typedef void (^OIMGroupsApplicationCallback)(NSArray <OIMGroupApplicationInfo *> * _Nullable groupsInfo);
|
||||||
|
typedef void (^OIMGroupInfoCallback)(OIMGroupInfo * _Nullable groupInfo);
|
||||||
|
typedef void (^OIMGroupsInfoCallback)(NSArray <OIMGroupInfo *> * _Nullable groupsInfo);
|
||||||
|
typedef void (^OIMGroupMemberInfoCallback)(OIMGroupMemberInfo * _Nullable groupMemberInfo);
|
||||||
|
typedef void (^OIMGroupMembersInfoCallback)(NSArray <OIMGroupMemberInfo *> * _Nullable groupMembersInfo);
|
||||||
|
|
||||||
|
typedef void (^OIMConversationsInfoCallback)(NSArray <OIMConversationInfo *> * _Nullable conversations);
|
||||||
|
typedef void (^OIMConversationInfoCallback)(OIMConversationInfo * _Nullable conversation);
|
||||||
|
typedef void (^OIMConversationNotDisturbInfoCallback)(NSArray <OIMConversationNotDisturbInfo *> * _Nullable conversations);
|
||||||
|
|
||||||
|
typedef void (^OIMMessageInfoCallback)(OIMMessageInfo * _Nullable message);
|
||||||
|
typedef void (^OIMMessagesInfoCallback)(NSArray <OIMMessageInfo *> * _Nullable messages);
|
||||||
|
typedef void (^OIMMessageSearchCallback)(OIMSearchResultInfo * _Nullable result);
|
||||||
|
|
||||||
|
typedef void (^OIMReceiptCallback)(NSArray <OIMReceiptInfo *> * _Nullable msgReceiptList);
|
||||||
|
typedef void (^OIMRevokedCallback)(OIMMessageRevokedInfo * _Nullable msgRovoked);
|
||||||
|
|
||||||
|
typedef void (^OIMGetAdvancedHistoryMessageListCallback)(OIMGetAdvancedHistoryMessageListInfo * _Nullable result);
|
||||||
|
|
||||||
|
typedef void (^OIMInputStatusChangedCallback)(NSArray<NSNumber *> *inputStatesChangedData);
|
||||||
|
|
||||||
|
/// IMSDK Core Callbacks
|
||||||
|
@protocol OIMSDKListener <NSObject>
|
||||||
|
@optional
|
||||||
|
/**
|
||||||
|
* SDK is connecting to the server.
|
||||||
|
*/
|
||||||
|
- (void)onConnecting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDK has successfully connected to the server.
|
||||||
|
*/
|
||||||
|
- (void)onConnectSuccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDK connection to the server has failed.
|
||||||
|
*/
|
||||||
|
- (void)onConnectFailed:(NSInteger)code err:(NSString *)err;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current user has been kicked offline. You can show a UI notification to the user.
|
||||||
|
*/
|
||||||
|
- (void)onKickedOffline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token has expired while online: You need to generate a new UserToken and re-login.
|
||||||
|
*/
|
||||||
|
- (void)onUserTokenExpired;
|
||||||
|
|
||||||
|
- (void)onUserTokenInvalid:(NSString *)errMsg;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// User Status Callbacks
|
||||||
|
@protocol OIMUserListener <NSObject>
|
||||||
|
@optional
|
||||||
|
/**
|
||||||
|
* User information has been updated.
|
||||||
|
*/
|
||||||
|
- (void)onSelfInfoUpdated:(OIMUserInfo *)info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User status has changed.
|
||||||
|
*/
|
||||||
|
- (void)onUserStatusChanged:(OIMUserStatusInfo *)info;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Profile and Relationship Callbacks
|
||||||
|
@protocol OIMFriendshipListener <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New friend application notification.
|
||||||
|
*/
|
||||||
|
- (void)onFriendApplicationAdded:(OIMFriendApplication *)application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friend application has been rejected.
|
||||||
|
*/
|
||||||
|
- (void)onFriendApplicationRejected:(OIMFriendApplication *)application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friend application has been accepted.
|
||||||
|
*/
|
||||||
|
- (void)onFriendApplicationAccepted:(OIMFriendApplication *)application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friend application has been deleted.
|
||||||
|
*/
|
||||||
|
- (void)onFriendApplicationDeleted:(OIMFriendApplication *)application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New friend notification.
|
||||||
|
*/
|
||||||
|
- (void)onFriendAdded:(OIMFriendInfo *)info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friend deletion notification.
|
||||||
|
*/
|
||||||
|
- (void)onFriendDeleted:(OIMFriendInfo *)info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friend profile change notification.
|
||||||
|
*/
|
||||||
|
- (void)onFriendInfoChanged:(OIMFriendInfo *)info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New blacklist notification.
|
||||||
|
*/
|
||||||
|
- (void)onBlackAdded:(OIMBlackInfo *)info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blacklist deletion notification.
|
||||||
|
*/
|
||||||
|
- (void)onBlackDeleted:(OIMBlackInfo *)info;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// IMSDK Group Event Callbacks
|
||||||
|
@protocol OIMGroupListener <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New member joined the group.
|
||||||
|
*/
|
||||||
|
- (void)onGroupMemberAdded:(OIMGroupMemberInfo *)memberInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Member left the group.
|
||||||
|
*/
|
||||||
|
- (void)onGroupMemberDeleted:(OIMGroupMemberInfo *)memberInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information of a member in the group has changed.
|
||||||
|
*/
|
||||||
|
- (void)onGroupMemberInfoChanged:(OIMGroupMemberInfo *)changeInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for group addition.
|
||||||
|
*/
|
||||||
|
- (void)onJoinedGroupAdded:(OIMGroupInfo *)groupInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for group removal.
|
||||||
|
*/
|
||||||
|
- (void)onJoinedGroupDeleted:(OIMGroupInfo *)groupInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information of a group that the user has joined has been modified.
|
||||||
|
*/
|
||||||
|
- (void)onGroupInfoChanged:(OIMGroupInfo *)changeInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group application has been accepted.
|
||||||
|
*/
|
||||||
|
- (void)onGroupApplicationAccepted:(OIMGroupApplicationInfo *)groupApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Someone has applied to join the group.
|
||||||
|
*/
|
||||||
|
- (void)onGroupApplicationAdded:(OIMGroupApplicationInfo *)groupApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group application has been deleted.
|
||||||
|
*/
|
||||||
|
- (void)onGroupApplicationDeleted:(OIMGroupApplicationInfo *)groupApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group application has been rejected.
|
||||||
|
*/
|
||||||
|
- (void)onGroupApplicationRejected:(OIMGroupApplicationInfo *)groupApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group has been disbanded.
|
||||||
|
*/
|
||||||
|
- (void)onGroupDismissed:(OIMGroupInfo *)changeInfo;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Conversation Event Callbacks
|
||||||
|
@protocol OIMConversationListener <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronization with the server has started for conversations.
|
||||||
|
*/
|
||||||
|
- (void)onSyncServerStart:(BOOL)reInstall;
|
||||||
|
|
||||||
|
- (void)onSyncServerProgress:(NSInteger)progress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronization with the server for conversations has completed.
|
||||||
|
*/
|
||||||
|
- (void)onSyncServerFinish:(BOOL)reInstall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronization with the server for conversations has failed.
|
||||||
|
*/
|
||||||
|
- (void)onSyncServerFailed:(BOOL)reInstall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New conversations have been added.
|
||||||
|
*/
|
||||||
|
- (void)onNewConversation:(NSArray <OIMConversationInfo *> *)conversations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key information of certain conversations has changed.
|
||||||
|
*/
|
||||||
|
- (void)onConversationChanged:(NSArray <OIMConversationInfo *> *)conversations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification of changes in the total unread message count of conversations.
|
||||||
|
*/
|
||||||
|
- (void)onTotalUnreadMessageCountChanged:(NSInteger)totalUnreadCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User input status updates.
|
||||||
|
*/
|
||||||
|
- (void)onConversationUserInputStatusChanged:(OIMInputStatusChangedData *)inputStatusChangedData;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Advanced Message Listener
|
||||||
|
@protocol OIMAdvancedMsgListener <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Received a new message.
|
||||||
|
*/
|
||||||
|
- (void)onRecvNewMessage:(OIMMessageInfo *)msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read receipt for one-on-one messages.
|
||||||
|
*/
|
||||||
|
- (void)onRecvC2CReadReceipt:(NSArray<OIMReceiptInfo *> *)receiptList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read receipt for group chat messages.
|
||||||
|
*/
|
||||||
|
- (void)onRecvGroupReadReceipt:(NSArray<OIMReceiptInfo *> *)groupMsgReceiptList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Received a message retraction.
|
||||||
|
*/
|
||||||
|
- (void)onRecvMessageRevoked:(OIMMessageRevokedInfo *)messageRevoked;
|
||||||
|
|
||||||
|
- (void)onMsgDeleted:(OIMMessageInfo *)message;
|
||||||
|
|
||||||
|
- (void)onRecvOnlineOnlyMessage:(OIMMessageInfo *)message;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Custom Business Callbacks for IM
|
||||||
|
@protocol OIMCustomBusinessListener <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
- (void)onRecvCustomBusinessMessage:(NSDictionary <NSString *, id>* _Nullable)businessMessage;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMCallbacker : NSObject
|
||||||
|
<
|
||||||
|
Open_im_sdk_callbackOnConnListener,
|
||||||
|
Open_im_sdk_callbackOnAdvancedMsgListener,
|
||||||
|
Open_im_sdk_callbackOnConversationListener,
|
||||||
|
Open_im_sdk_callbackOnFriendshipListener,
|
||||||
|
Open_im_sdk_callbackOnGroupListener,
|
||||||
|
Open_im_sdk_callbackOnUserListener,
|
||||||
|
Open_im_sdk_callbackOnCustomBusinessListener
|
||||||
|
>
|
||||||
|
|
||||||
|
+ (instancetype)callbacker;
|
||||||
|
|
||||||
|
- (void)setListener;
|
||||||
|
|
||||||
|
/// Connection Listener
|
||||||
|
/// Set during InitSDK, called when the IM connection status changes.
|
||||||
|
@property (nonatomic, nullable, copy) OIMVoidCallback connecting;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFailureCallback connectFailure;
|
||||||
|
@property (nonatomic, nullable, copy) OIMVoidCallback connectSuccess;
|
||||||
|
@property (nonatomic, nullable, copy) OIMVoidCallback kickedOffline;
|
||||||
|
@property (nonatomic, nullable, copy) OIMVoidCallback userTokenExpired;
|
||||||
|
@property (nonatomic, nullable, copy) OIMStringCallback userTokenInvalid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add IM SDK listener.
|
||||||
|
*/
|
||||||
|
- (void)addIMSDKListener:(id<OIMSDKListener>)listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove IM SDK listener.
|
||||||
|
*/
|
||||||
|
- (void)removeIMSDKListener:(id<OIMSDKListener>)listener;
|
||||||
|
|
||||||
|
/// User Listener
|
||||||
|
/// Set after a successful InitSDK and before Login, called when the personal profile of the logged-in user changes.
|
||||||
|
@property (nonatomic, nullable, copy) OIMUserInfoCallback onSelfInfoUpdated;
|
||||||
|
@property (nonatomic, nullable, copy) OIMUserStatusInfoCallback onUserStatusChanged;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add User listener.
|
||||||
|
*/
|
||||||
|
- (void)addUserListener:(id<OIMUserListener>)listener NS_SWIFT_NAME(addUserListener(listener:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove User listener.
|
||||||
|
*/
|
||||||
|
- (void)removeUserListener:(id<OIMUserListener>)listener NS_SWIFT_NAME(removeUserListener(listener:));
|
||||||
|
|
||||||
|
/// Friendship Listener
|
||||||
|
/// Set after a successful InitSDK and before Login, called when friend-related information changes.
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendApplicationCallback onFriendApplicationAdded;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendApplicationCallback onFriendApplicationDeleted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendApplicationCallback onFriendApplicationAccepted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendApplicationCallback onFriendApplicationRejected;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendInfoCallback onFriendAdded;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendInfoCallback onFriendDeleted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMFriendInfoCallback onFriendInfoChanged;
|
||||||
|
@property (nonatomic, nullable, copy) OIMBlackInfoCallback onBlackAdded;
|
||||||
|
@property (nonatomic, nullable, copy) OIMBlackInfoCallback onBlackDeleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Friendship listener.
|
||||||
|
*/
|
||||||
|
- (void)addFriendListener:(id<OIMFriendshipListener>)listener NS_SWIFT_NAME(addFriendListener(listener:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove Friendship listener.
|
||||||
|
*/
|
||||||
|
- (void)removeFriendListener:(id<OIMFriendshipListener>)listener NS_SWIFT_NAME(removeFriendListener(listener:));
|
||||||
|
|
||||||
|
/// Group Listener
|
||||||
|
/// Set after a successful InitSDK and before Login, called when group-related information changes.
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupInfoCallback onGroupInfoChanged;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupInfoCallback onJoinedGroupAdded;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupInfoCallback onJoinedGroupDeleted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupMemberInfoCallback onGroupMemberAdded;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupMemberInfoCallback onGroupMemberDeleted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupMemberInfoCallback onGroupMemberInfoChanged;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupApplicationCallback onGroupApplicationAdded;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupApplicationCallback onGroupApplicationDeleted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupApplicationCallback onGroupApplicationAccepted;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupApplicationCallback onGroupApplicationRejected;
|
||||||
|
@property (nonatomic, nullable, copy) OIMGroupInfoCallback onGroupDismissed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group listener.
|
||||||
|
*/
|
||||||
|
- (void)addGroupListener:(id<OIMGroupListener>)listener NS_SWIFT_NAME(addGroupListener(listener:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove group listener.
|
||||||
|
*/
|
||||||
|
- (void)removeGroupListener:(id<OIMGroupListener>)listener NS_SWIFT_NAME(removeGroupListener(listener:));
|
||||||
|
|
||||||
|
/// Conversation Listener
|
||||||
|
/// Set after a successful InitSDK and before Login, called when conversation-related information changes.
|
||||||
|
@property (nonatomic, nullable, copy) OIMBoolCallback syncServerStart;
|
||||||
|
@property (nonatomic, nullable, copy) OIMBoolCallback syncServerFinish;
|
||||||
|
@property (nonatomic, nullable, copy) OIMBoolCallback syncServerFailed;
|
||||||
|
@property (nonatomic, nullable, copy) OIMNumberCallback syncServerProgress;
|
||||||
|
@property (nonatomic, nullable, copy) OIMConversationsInfoCallback onNewConversation;
|
||||||
|
@property (nonatomic, nullable, copy) OIMConversationsInfoCallback onConversationChanged;
|
||||||
|
@property (nonatomic, nullable, copy) OIMNumberCallback onTotalUnreadMessageCountChanged;
|
||||||
|
@property (nonatomic, nullable, copy) OIMInputStatusChangedCallback onConversationUserInputStatusChanged;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add conversation listener.
|
||||||
|
*/
|
||||||
|
- (void)addConversationListener:(id<OIMConversationListener>)listener NS_SWIFT_NAME(addConversationListener(listener:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove conversation listener.
|
||||||
|
*/
|
||||||
|
- (void)removeConversationListener:(id<OIMConversationListener>)listener NS_SWIFT_NAME(removeConversationListener(listener:));
|
||||||
|
|
||||||
|
/// Message Listener
|
||||||
|
/// Set after a successful InitSDK and before Login, called when message-related information changes.
|
||||||
|
@property (nonatomic, nullable, copy) OIMMessageInfoCallback onRecvNewMessage;
|
||||||
|
@property (nonatomic, nullable, copy) OIMReceiptCallback onRecvC2CReadReceipt;
|
||||||
|
@property (nonatomic, nullable, copy) OIMReceiptCallback onRecvGroupReadReceipt;
|
||||||
|
@property (nonatomic, nullable, copy) OIMRevokedCallback onRecvMessageRevoked;
|
||||||
|
@property (nonatomic, nullable, copy) OIMMessageInfoCallback onMessageDeleted;
|
||||||
|
/**
|
||||||
|
* Add advanced message event listener.
|
||||||
|
*/
|
||||||
|
- (void)addAdvancedMsgListener:(id<OIMAdvancedMsgListener>)listener NS_SWIFT_NAME(addAdvancedMsgListener(listener:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove advanced message event listener.
|
||||||
|
*/
|
||||||
|
- (void)removeAdvancedMsgListener:(id<OIMAdvancedMsgListener>)listener NS_SWIFT_NAME(removeAdvancedMsgListener(listener:));
|
||||||
|
|
||||||
|
/// Custom Business Message Listener
|
||||||
|
@property (nonatomic, nullable, copy) OIMObjectCallback onRecvCustomBusinessMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add IM listener for custom business events.
|
||||||
|
*/
|
||||||
|
- (void)addCustomBusinessListener:(id<OIMCustomBusinessListener>)listener NS_SWIFT_NAME(addCustomBusinessListener(listener:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove IM listener for custom business events.
|
||||||
|
*/
|
||||||
|
- (void)removeCustomBusinessListener:(id<OIMCustomBusinessListener>)listener NS_SWIFT_NAME(removeCustomBusinessListener(listener:));
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,674 @@
|
||||||
|
//
|
||||||
|
// OIMCallbacker.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2021/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMCallbacker.h"
|
||||||
|
#import "OIMGCDMulticastDelegate.h"
|
||||||
|
|
||||||
|
@interface OIMCallbacker ()
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMSDKListener> *sdkListeners;
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMUserListener> *userListeners;
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMFriendshipListener> *friendshipListeners;
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMGroupListener> *groupListeners;
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMConversationListener> *conversationListeners;
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMAdvancedMsgListener> *advancedMsgListeners;
|
||||||
|
@property (nonatomic, strong) OIMGCDMulticastDelegate <OIMCustomBusinessListener> *customBusinessListeners;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMCallbacker
|
||||||
|
|
||||||
|
+ (instancetype)callbacker {
|
||||||
|
return [OIMCallbacker new];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setListener {
|
||||||
|
Open_im_sdkSetUserListener(self);
|
||||||
|
Open_im_sdkSetFriendListener(self);
|
||||||
|
Open_im_sdkSetGroupListener(self);
|
||||||
|
Open_im_sdkSetConversationListener(self);
|
||||||
|
Open_im_sdkSetAdvancedMsgListener(self);
|
||||||
|
Open_im_sdkSetCustomBusinessListener(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dispatchMainThread:(void (NS_NOESCAPE ^)(void))todo {
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
todo();
|
||||||
|
} else {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
todo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Listeners getter
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMSDKListener> *)sdkListeners {
|
||||||
|
if (_sdkListeners == nil) {
|
||||||
|
_sdkListeners = (OIMGCDMulticastDelegate <OIMSDKListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _sdkListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMUserListener> *)userListeners {
|
||||||
|
if (_userListeners == nil) {
|
||||||
|
_userListeners = (OIMGCDMulticastDelegate <OIMUserListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _userListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMFriendshipListener> *)friendshipListeners {
|
||||||
|
if (_friendshipListeners == nil) {
|
||||||
|
_friendshipListeners = (OIMGCDMulticastDelegate <OIMFriendshipListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _friendshipListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMGroupListener> *)groupListeners {
|
||||||
|
if (_groupListeners == nil) {
|
||||||
|
_groupListeners = (OIMGCDMulticastDelegate <OIMGroupListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _groupListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMConversationListener> *)conversationListeners {
|
||||||
|
if (_conversationListeners == nil) {
|
||||||
|
_conversationListeners = (OIMGCDMulticastDelegate <OIMConversationListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _conversationListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMAdvancedMsgListener> *)advancedMsgListeners {
|
||||||
|
if (_advancedMsgListeners == nil) {
|
||||||
|
_advancedMsgListeners = (OIMGCDMulticastDelegate <OIMAdvancedMsgListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _advancedMsgListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegate<OIMCustomBusinessListener> *)customBusinessListeners {
|
||||||
|
if (_customBusinessListeners == nil) {
|
||||||
|
_customBusinessListeners = (OIMGCDMulticastDelegate <OIMCustomBusinessListener> *)[[OIMGCDMulticastDelegate alloc] init];
|
||||||
|
}
|
||||||
|
return _customBusinessListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Add/Remove listener
|
||||||
|
|
||||||
|
- (void)addIMSDKListener:(id<OIMSDKListener>)listener {
|
||||||
|
[self.sdkListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeIMSDKListener:(id<OIMSDKListener>)listener {
|
||||||
|
[self.sdkListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addUserListener:(id<OIMUserListener>)listener {
|
||||||
|
[self.userListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeUserListener:(id<OIMUserListener>)listener {
|
||||||
|
[self.userListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addFriendListener:(id<OIMFriendshipListener>)listener {
|
||||||
|
[self.friendshipListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeFriendListener:(id<OIMFriendshipListener>)listener {
|
||||||
|
[self.friendshipListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addGroupListener:(id<OIMGroupListener>)listener {
|
||||||
|
[self.groupListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeGroupListener:(id<OIMGroupListener>)listener {
|
||||||
|
[self.groupListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addConversationListener:(id<OIMConversationListener>)listener {
|
||||||
|
[self.conversationListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeConversationListener:(id<OIMConversationListener>)listener {
|
||||||
|
[self.conversationListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addAdvancedMsgListener:(id<OIMAdvancedMsgListener>)listener {
|
||||||
|
[self.advancedMsgListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeAdvancedMsgListener:(id<OIMAdvancedMsgListener>)listener {
|
||||||
|
[self.advancedMsgListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addCustomBusinessListener:(id<OIMCustomBusinessListener>)listener {
|
||||||
|
[self.customBusinessListeners addDelegate:listener delegateQueue:dispatch_get_main_queue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeCustomBusinessListener:(id<OIMCustomBusinessListener>)listener {
|
||||||
|
[self.customBusinessListeners removeDelegate:listener];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Connection
|
||||||
|
|
||||||
|
- (void)onConnectFailed:(int32_t)errCode errMsg:(NSString * _Nullable)errMsg {
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.connectFailure) {
|
||||||
|
self.connectFailure(errCode, errMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.sdkListeners onConnectFailed:errCode err:errMsg];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onConnectSuccess {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.connectSuccess) {
|
||||||
|
self.connectSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.sdkListeners onConnectSuccess];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onConnecting {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.connecting) {
|
||||||
|
self.connecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.sdkListeners onConnecting];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onKickedOffline {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.kickedOffline) {
|
||||||
|
self.kickedOffline();
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.sdkListeners onKickedOffline];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onUserTokenExpired {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.userTokenExpired) {
|
||||||
|
self.userTokenExpired();
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.sdkListeners onUserTokenExpired];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onUserTokenInvalid:(NSString *)errMsg {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.userTokenInvalid) {
|
||||||
|
self.userTokenInvalid(errMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.sdkListeners onUserTokenInvalid:errMsg];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - User
|
||||||
|
|
||||||
|
- (void)onSelfInfoUpdated:(NSString * _Nullable)userInfo {
|
||||||
|
OIMUserInfo *info = [OIMUserInfo mj_objectWithKeyValues:userInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onSelfInfoUpdated) {
|
||||||
|
self.onSelfInfoUpdated(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.userListeners onSelfInfoUpdated:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onUserStatusChanged:(NSString *)statusMap {
|
||||||
|
OIMUserStatusInfo *info = [OIMUserStatusInfo mj_objectWithKeyValues:statusMap];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onUserStatusChanged) {
|
||||||
|
self.onUserStatusChanged(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.userListeners onUserStatusChanged:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onUserCommandAdd:(NSString * _Nullable)userCommand {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)onUserCommandDelete:(NSString * _Nullable)userCommand {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)onUserCommandUpdate:(NSString * _Nullable)userCommand {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Friend
|
||||||
|
|
||||||
|
- (void)onFriendApplicationAdded:(NSString * _Nullable)friendApplication {
|
||||||
|
OIMFriendApplication *info = [OIMFriendApplication mj_objectWithKeyValues:friendApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendApplicationAdded) {
|
||||||
|
self.onFriendApplicationAdded(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendApplicationAdded:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onFriendApplicationRejected:(NSString * _Nullable)friendApplication {
|
||||||
|
OIMFriendApplication *info = [OIMFriendApplication mj_objectWithKeyValues:friendApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendApplicationRejected) {
|
||||||
|
self.onFriendApplicationRejected(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendApplicationRejected:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onFriendApplicationAccepted:(NSString * _Nullable)friendApplication {
|
||||||
|
OIMFriendApplication *info = [OIMFriendApplication mj_objectWithKeyValues:friendApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendApplicationAccepted) {
|
||||||
|
self.onFriendApplicationAccepted(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendApplicationAccepted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onFriendApplicationDeleted:(NSString * _Nullable)friendApplication {
|
||||||
|
OIMFriendApplication *info = [OIMFriendApplication mj_objectWithKeyValues:friendApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendApplicationDeleted) {
|
||||||
|
self.onFriendApplicationDeleted(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendApplicationDeleted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onFriendAdded:(NSString * _Nullable)friendInfo {
|
||||||
|
OIMFriendInfo *info = [OIMFriendInfo mj_objectWithKeyValues:friendInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendAdded) {
|
||||||
|
self.onFriendAdded(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendAdded:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onFriendDeleted:(NSString * _Nullable)friendInfo {
|
||||||
|
OIMFriendInfo *info = [OIMFriendInfo mj_objectWithKeyValues:friendInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendDeleted) {
|
||||||
|
self.onFriendDeleted(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendDeleted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onFriendInfoChanged:(NSString * _Nullable)friendInfo {
|
||||||
|
OIMFriendInfo *info = [OIMFriendInfo mj_objectWithKeyValues:friendInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onFriendInfoChanged) {
|
||||||
|
self.onFriendInfoChanged(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onFriendInfoChanged:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onBlackAdded:(NSString* _Nullable)blackInfo {
|
||||||
|
OIMBlackInfo *info = [OIMBlackInfo mj_objectWithKeyValues:blackInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onBlackAdded) {
|
||||||
|
self.onBlackAdded(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onBlackAdded:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onBlackDeleted:(NSString * _Nullable)blackInfo {
|
||||||
|
OIMBlackInfo *info = [OIMBlackInfo mj_objectWithKeyValues:blackInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onBlackDeleted) {
|
||||||
|
self.onBlackDeleted(info);
|
||||||
|
}
|
||||||
|
[self.friendshipListeners onBlackDeleted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Group
|
||||||
|
|
||||||
|
- (void)onGroupMemberAdded:(NSString * _Nullable)groupMemberInfo {
|
||||||
|
OIMGroupMemberInfo *info = [OIMGroupMemberInfo mj_objectWithKeyValues:groupMemberInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupMemberAdded) {
|
||||||
|
self.onGroupMemberAdded(info);
|
||||||
|
}
|
||||||
|
[self.groupListeners onGroupMemberAdded:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupMemberDeleted:(NSString * _Nullable)groupMemberInfo {
|
||||||
|
OIMGroupMemberInfo *info = [OIMGroupMemberInfo mj_objectWithKeyValues:groupMemberInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupMemberDeleted) {
|
||||||
|
self.onGroupMemberDeleted(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupMemberDeleted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupMemberInfoChanged:(NSString * _Nullable)groupMemberInfo {
|
||||||
|
OIMGroupMemberInfo *info = [OIMGroupMemberInfo mj_objectWithKeyValues:groupMemberInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupMemberInfoChanged) {
|
||||||
|
self.onGroupMemberInfoChanged(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupMemberInfoChanged:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupInfoChanged:(NSString * _Nullable)groupInfo {
|
||||||
|
OIMGroupInfo *info = [OIMGroupInfo mj_objectWithKeyValues:groupInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupInfoChanged) {
|
||||||
|
self.onGroupInfoChanged(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupInfoChanged:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onJoinedGroupAdded:(NSString * _Nullable)groupInfo {
|
||||||
|
OIMGroupInfo *info = [OIMGroupInfo mj_objectWithKeyValues:groupInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onJoinedGroupAdded) {
|
||||||
|
self.onJoinedGroupAdded(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onJoinedGroupAdded:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onJoinedGroupDeleted:(NSString * _Nullable)groupInfo {
|
||||||
|
OIMGroupInfo *info = [OIMGroupInfo mj_objectWithKeyValues:groupInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onJoinedGroupDeleted) {
|
||||||
|
self.onJoinedGroupDeleted(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onJoinedGroupDeleted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupApplicationAccepted:(NSString * _Nullable)groupApplication {
|
||||||
|
OIMGroupApplicationInfo *info = [OIMGroupApplicationInfo mj_objectWithKeyValues:groupApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupApplicationAccepted) {
|
||||||
|
self.onGroupApplicationAccepted(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupApplicationAccepted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupApplicationAdded:(NSString * _Nullable)groupApplication {
|
||||||
|
OIMGroupApplicationInfo *info = [OIMGroupApplicationInfo mj_objectWithKeyValues:groupApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupApplicationAdded) {
|
||||||
|
self.onGroupApplicationAdded(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupApplicationAdded:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupApplicationDeleted:(NSString * _Nullable)groupApplication {
|
||||||
|
OIMGroupApplicationInfo *info = [OIMGroupApplicationInfo mj_objectWithKeyValues:groupApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupApplicationDeleted) {
|
||||||
|
self.onGroupApplicationDeleted(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupApplicationDeleted:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupApplicationRejected:(NSString * _Nullable)groupApplication {
|
||||||
|
OIMGroupApplicationInfo *info = [OIMGroupApplicationInfo mj_objectWithKeyValues:groupApplication];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupApplicationRejected) {
|
||||||
|
self.onGroupApplicationRejected(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupApplicationRejected:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onGroupDismissed:(NSString *)groupInfo {
|
||||||
|
OIMGroupInfo *info = [OIMGroupInfo mj_objectWithKeyValues:groupInfo];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onGroupDismissed) {
|
||||||
|
self.onGroupDismissed(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.groupListeners onGroupDismissed:info];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Message
|
||||||
|
|
||||||
|
- (void)onRecvC2CReadReceipt:(NSString * _Nullable)msgReceiptList {
|
||||||
|
NSArray *receipts = [OIMReceiptInfo mj_objectArrayWithKeyValuesArray:msgReceiptList];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onRecvC2CReadReceipt) {
|
||||||
|
self.onRecvC2CReadReceipt(receipts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.advancedMsgListeners onRecvC2CReadReceipt:receipts];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onRecvGroupReadReceipt:(NSString* _Nullable)groupMsgReceiptList {
|
||||||
|
NSArray *receipts = [OIMReceiptInfo mj_objectArrayWithKeyValuesArray:groupMsgReceiptList];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onRecvGroupReadReceipt) {
|
||||||
|
self.onRecvGroupReadReceipt(receipts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.advancedMsgListeners onRecvGroupReadReceipt:receipts];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onNewRecvMessageRevoked:(NSString *)messageRevoked {
|
||||||
|
|
||||||
|
OIMMessageRevokedInfo *revoked = [OIMMessageRevokedInfo mj_objectWithKeyValues:messageRevoked];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onRecvMessageRevoked) {
|
||||||
|
self.onRecvMessageRevoked(revoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.advancedMsgListeners onRecvMessageRevoked:revoked];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onRecvNewMessage:(NSString * _Nullable)message {
|
||||||
|
OIMMessageInfo *msg = [OIMMessageInfo mj_objectWithKeyValues:message];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onRecvNewMessage) {
|
||||||
|
self.onRecvNewMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.advancedMsgListeners onRecvNewMessage:msg];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onMsgDeleted:(NSString *)message {
|
||||||
|
OIMMessageInfo *msg = [OIMMessageInfo mj_objectWithKeyValues:message];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onMessageDeleted) {
|
||||||
|
self.onMessageDeleted(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.advancedMsgListeners onMsgDeleted:msg];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onRecvOfflineNewMessage:(NSString * _Nullable)message {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onRecvOnlineOnlyMessage:(NSString *)message {
|
||||||
|
OIMMessageInfo *msg = [OIMMessageInfo mj_objectWithKeyValues:message];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
[self.advancedMsgListeners onRecvOnlineOnlyMessage:msg];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Conversation
|
||||||
|
|
||||||
|
- (void)onConversationChanged:(NSString * _Nullable)conversationList {
|
||||||
|
|
||||||
|
NSArray *tConversations = [OIMConversationInfo mj_objectArrayWithKeyValuesArray:conversationList];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onConversationChanged) {
|
||||||
|
self.onConversationChanged(tConversations);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onConversationChanged:tConversations];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onNewConversation:(NSString * _Nullable)conversationList {
|
||||||
|
|
||||||
|
NSArray *tConversations = [OIMConversationInfo mj_objectArrayWithKeyValuesArray:conversationList];
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onNewConversation) {
|
||||||
|
self.onNewConversation(tConversations);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onNewConversation:tConversations];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onSyncServerFailed:(BOOL)reinstalled {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.syncServerFailed) {
|
||||||
|
self.syncServerFailed(reinstalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onSyncServerFailed:reinstalled];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onSyncServerFinish:(BOOL)reinstalled {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.syncServerFinish) {
|
||||||
|
self.syncServerFinish(reinstalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onSyncServerFinish:reinstalled];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onSyncServerStart:(BOOL)reinstalled {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.syncServerStart) {
|
||||||
|
self.syncServerStart(reinstalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onSyncServerStart:reinstalled];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onSyncServerProgress:(long)progress {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.syncServerStart) {
|
||||||
|
self.syncServerStart(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onSyncServerProgress:progress];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onTotalUnreadMessageCountChanged:(int32_t)totalUnreadCount {
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onTotalUnreadMessageCountChanged) {
|
||||||
|
self.onTotalUnreadMessageCountChanged(totalUnreadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.conversationListeners onTotalUnreadMessageCountChanged:totalUnreadCount];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onConversationUserInputStatusChanged:(NSString *)change {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - CustomBusiness
|
||||||
|
|
||||||
|
- (void)onRecvCustomBusinessMessage:(NSString *)businessMessage {
|
||||||
|
NSDictionary *output = businessMessage.mj_JSONObject;
|
||||||
|
|
||||||
|
[self dispatchMainThread:^{
|
||||||
|
if (self.onRecvCustomBusinessMessage) {
|
||||||
|
self.onRecvCustomBusinessMessage(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.customBusinessListeners onRecvCustomBusinessMessage:output];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class OIMGCDMulticastDelegateEnumerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides multicast delegate functionality. That is:
|
||||||
|
* - it provides a means for managing a list of delegates
|
||||||
|
* - any method invocations to an instance of this class are automatically forwarded to all delegates
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* // Make this method call on every added delegate (there may be several)
|
||||||
|
* [multicastDelegate cog:self didFindThing:thing];
|
||||||
|
*
|
||||||
|
* This allows multiple delegates to be added to an xmpp stream or any xmpp module,
|
||||||
|
* which in turn makes development easier as there can be proper separation of logically different code sections.
|
||||||
|
*
|
||||||
|
* In addition, this makes module development easier,
|
||||||
|
* as multiple delegates can usually be handled in a manner similar to the traditional single delegate paradigm.
|
||||||
|
*
|
||||||
|
* This class also provides proper support for GCD queues.
|
||||||
|
* So each delegate specifies which queue they would like their delegate invocations to be dispatched onto.
|
||||||
|
*
|
||||||
|
* All delegate dispatching is done asynchronously (which is a critically important architectural design).
|
||||||
|
**/
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
@interface OIMGCDMulticastDelegate : NSObject
|
||||||
|
|
||||||
|
- (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
|
||||||
|
- (void)removeDelegate:(id)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||||
|
- (void)removeDelegate:(id)delegate;
|
||||||
|
|
||||||
|
- (void)removeAllDelegates;
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) NSUInteger count;
|
||||||
|
- (NSUInteger)countOfClass:(Class)aClass;
|
||||||
|
- (NSUInteger)countForSelector:(SEL)aSelector;
|
||||||
|
|
||||||
|
- (BOOL)hasDelegateThatRespondsToSelector:(SEL)aSelector;
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegateEnumerator *)delegateEnumerator;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@interface OIMGCDMulticastDelegateEnumerator : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) NSUInteger count;
|
||||||
|
- (NSUInteger)countOfClass:(Class)aClass;
|
||||||
|
- (NSUInteger)countForSelector:(SEL)aSelector;
|
||||||
|
|
||||||
|
- (BOOL)getNextDelegate:(id _Nullable * _Nonnull)delPtr delegateQueue:(dispatch_queue_t _Nullable * _Nonnull)dqPtr;
|
||||||
|
- (BOOL)getNextDelegate:(id _Nullable * _Nonnull)delPtr delegateQueue:(dispatch_queue_t _Nullable * _Nonnull)dqPtr ofClass:(Class)aClass;
|
||||||
|
- (BOOL)getNextDelegate:(id _Nullable * _Nonnull)delPtr delegateQueue:(dispatch_queue_t _Nullable * _Nonnull)dqPtr forSelector:(SEL)aSelector;
|
||||||
|
|
||||||
|
@end
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,654 @@
|
||||||
|
#import "OIMGCDMulticastDelegate.h"
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ! __has_feature(objc_arc)
|
||||||
|
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How does this class work?
|
||||||
|
*
|
||||||
|
* In theory, this class is very straight-forward.
|
||||||
|
* It provides a way for multiple delegates to be called, each on its own delegate queue.
|
||||||
|
*
|
||||||
|
* In other words, any delegate method call to this class
|
||||||
|
* will get forwarded (dispatch_async'd) to each added delegate.
|
||||||
|
*
|
||||||
|
* Important note concerning thread-safety:
|
||||||
|
*
|
||||||
|
* This class is designed to be used from within a single dispatch queue.
|
||||||
|
* In other words, it is NOT thread-safe, and should only be used from within the external dedicated dispatch_queue.
|
||||||
|
**/
|
||||||
|
|
||||||
|
@interface OIMGCDMulticastDelegateNode : NSObject {
|
||||||
|
@private
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc_weak)
|
||||||
|
__weak id delegate;
|
||||||
|
#if !TARGET_OS_IPHONE
|
||||||
|
__unsafe_unretained id unsafeDelegate; // Some classes don't support weak references yet (e.g. NSWindowController)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
__unsafe_unretained id delegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dispatch_queue_t delegateQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc_weak)
|
||||||
|
@property (/* atomic */ readwrite, weak) id delegate;
|
||||||
|
#if !TARGET_OS_IPHONE
|
||||||
|
@property (/* atomic */ readwrite, unsafe_unretained) id unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
@property (/* atomic */ readwrite, unsafe_unretained) id delegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) dispatch_queue_t delegateQueue;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@interface OIMGCDMulticastDelegate ()
|
||||||
|
{
|
||||||
|
NSMutableArray *delegateNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInvocation *)duplicateInvocation:(NSInvocation *)origInvocation;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@interface OIMGCDMulticastDelegateEnumerator ()
|
||||||
|
{
|
||||||
|
NSUInteger numNodes;
|
||||||
|
NSUInteger currentNodeIndex;
|
||||||
|
NSArray *delegateNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initFromDelegateNodes:(NSMutableArray *)inDelegateNodes;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#pragma mark -
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@implementation OIMGCDMulticastDelegate
|
||||||
|
|
||||||
|
- (id)init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
delegateNodes = [[NSMutableArray alloc] init];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue
|
||||||
|
{
|
||||||
|
if (delegate == nil) return;
|
||||||
|
if (delegateQueue == NULL) return;
|
||||||
|
|
||||||
|
OIMGCDMulticastDelegateNode *node =
|
||||||
|
[[OIMGCDMulticastDelegateNode alloc] initWithDelegate:delegate delegateQueue:delegateQueue];
|
||||||
|
|
||||||
|
[delegateNodes addObject:node];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue
|
||||||
|
{
|
||||||
|
if (delegate == nil) return;
|
||||||
|
|
||||||
|
NSUInteger i;
|
||||||
|
for (i = [delegateNodes count]; i > 0; i--)
|
||||||
|
{
|
||||||
|
OIMGCDMulticastDelegateNode *node = delegateNodes[i - 1];
|
||||||
|
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (delegate == nodeDelegate)
|
||||||
|
{
|
||||||
|
if ((delegateQueue == NULL) || (delegateQueue == node.delegateQueue))
|
||||||
|
{
|
||||||
|
// Recall that this node may be retained by a OIMGCDMulticastDelegateEnumerator.
|
||||||
|
// The enumerator is a thread-safe snapshot of the delegate list at the moment it was created.
|
||||||
|
// To properly remove this node from list, and from the list(s) of any enumerators,
|
||||||
|
// we nullify the delegate via the atomic property.
|
||||||
|
//
|
||||||
|
// However, the delegateQueue is not modified.
|
||||||
|
// The thread-safety is hinged on the atomic delegate property.
|
||||||
|
// The delegateQueue is expected to properly exist until the node is deallocated.
|
||||||
|
|
||||||
|
node.delegate = nil;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
node.unsafeDelegate = nil;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[delegateNodes removeObjectAtIndex:(i-1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeDelegate:(id)delegate
|
||||||
|
{
|
||||||
|
[self removeDelegate:delegate delegateQueue:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeAllDelegates
|
||||||
|
{
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
node.delegate = nil;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
node.unsafeDelegate = nil;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[delegateNodes removeAllObjects];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)count
|
||||||
|
{
|
||||||
|
return [delegateNodes count];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)countOfClass:(Class)aClass
|
||||||
|
{
|
||||||
|
NSUInteger count = 0;
|
||||||
|
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate isKindOfClass:aClass])
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)countForSelector:(SEL)aSelector
|
||||||
|
{
|
||||||
|
NSUInteger count = 0;
|
||||||
|
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate respondsToSelector:aSelector])
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasDelegateThatRespondsToSelector:(SEL)aSelector
|
||||||
|
{
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate respondsToSelector:aSelector])
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMGCDMulticastDelegateEnumerator *)delegateEnumerator
|
||||||
|
{
|
||||||
|
return [[OIMGCDMulticastDelegateEnumerator alloc] initFromDelegateNodes:delegateNodes];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
|
||||||
|
{
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NSMethodSignature *result = [nodeDelegate methodSignatureForSelector:aSelector];
|
||||||
|
|
||||||
|
if (result != nil)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This causes a crash...
|
||||||
|
// return [super methodSignatureForSelector:aSelector];
|
||||||
|
|
||||||
|
// This also causes a crash...
|
||||||
|
// return nil;
|
||||||
|
|
||||||
|
return [[self class] instanceMethodSignatureForSelector:@selector(doNothing)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)forwardInvocation:(NSInvocation *)origInvocation
|
||||||
|
{
|
||||||
|
SEL selector = [origInvocation selector];
|
||||||
|
BOOL foundNilDelegate = NO;
|
||||||
|
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate respondsToSelector:selector])
|
||||||
|
{
|
||||||
|
// All delegates MUST be invoked ASYNCHRONOUSLY.
|
||||||
|
|
||||||
|
NSInvocation *dupInvocation = [self duplicateInvocation:origInvocation];
|
||||||
|
|
||||||
|
dispatch_async(node.delegateQueue, ^{ @autoreleasepool {
|
||||||
|
|
||||||
|
[dupInvocation invokeWithTarget:nodeDelegate];
|
||||||
|
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
else if (nodeDelegate == nil)
|
||||||
|
{
|
||||||
|
foundNilDelegate = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundNilDelegate)
|
||||||
|
{
|
||||||
|
// At lease one weak delegate reference disappeared.
|
||||||
|
// Remove nil delegate nodes from the list.
|
||||||
|
//
|
||||||
|
// This is expected to happen very infrequently.
|
||||||
|
// This is why we handle it separately (as it requires allocating an indexSet).
|
||||||
|
|
||||||
|
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
|
||||||
|
|
||||||
|
NSUInteger i = 0;
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (nodeDelegate == nil)
|
||||||
|
{
|
||||||
|
[indexSet addIndex:i];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[delegateNodes removeObjectsAtIndexes:indexSet];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)doesNotRecognizeSelector:(SEL)aSelector
|
||||||
|
{
|
||||||
|
// Prevent NSInvalidArgumentException
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)doNothing {}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[self removeAllDelegates];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInvocation *)duplicateInvocation:(NSInvocation *)origInvocation
|
||||||
|
{
|
||||||
|
NSMethodSignature *methodSignature = [origInvocation methodSignature];
|
||||||
|
|
||||||
|
NSInvocation *dupInvocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
||||||
|
[dupInvocation setSelector:[origInvocation selector]];
|
||||||
|
|
||||||
|
NSUInteger i, count = [methodSignature numberOfArguments];
|
||||||
|
for (i = 2; i < count; i++)
|
||||||
|
{
|
||||||
|
const char *type = [methodSignature getArgumentTypeAtIndex:i];
|
||||||
|
|
||||||
|
if (*type == *@encode(BOOL))
|
||||||
|
{
|
||||||
|
BOOL value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(char) || *type == *@encode(unsigned char))
|
||||||
|
{
|
||||||
|
char value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(short) || *type == *@encode(unsigned short))
|
||||||
|
{
|
||||||
|
short value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(int) || *type == *@encode(unsigned int))
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(long) || *type == *@encode(unsigned long))
|
||||||
|
{
|
||||||
|
long value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(long long) || *type == *@encode(unsigned long long))
|
||||||
|
{
|
||||||
|
long long value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(double))
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == *@encode(float))
|
||||||
|
{
|
||||||
|
float value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == '@')
|
||||||
|
{
|
||||||
|
void *value;
|
||||||
|
[origInvocation getArgument:&value atIndex:i];
|
||||||
|
[dupInvocation setArgument:&value atIndex:i];
|
||||||
|
}
|
||||||
|
else if (*type == '^')
|
||||||
|
{
|
||||||
|
void *block;
|
||||||
|
[origInvocation getArgument:&block atIndex:i];
|
||||||
|
[dupInvocation setArgument:&block atIndex:i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString *selectorStr = NSStringFromSelector([origInvocation selector]);
|
||||||
|
|
||||||
|
NSString *format = @"Argument %lu to method %@ - Type(%c) not supported";
|
||||||
|
NSString *reason = [NSString stringWithFormat:format, (unsigned long)(i - 2), selectorStr, *type];
|
||||||
|
|
||||||
|
[[NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil] raise];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[dupInvocation retainArguments];
|
||||||
|
|
||||||
|
return dupInvocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#pragma mark -
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@implementation OIMGCDMulticastDelegateNode
|
||||||
|
|
||||||
|
@synthesize delegate; // atomic
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
@synthesize unsafeDelegate; // atomic
|
||||||
|
#endif
|
||||||
|
@synthesize delegateQueue; // non-atomic
|
||||||
|
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
static BOOL SupportsWeakReferences(id delegate)
|
||||||
|
{
|
||||||
|
// From Apple's documentation:
|
||||||
|
//
|
||||||
|
// > Which classes don’t support weak references?
|
||||||
|
// >
|
||||||
|
// > You cannot currently create weak references to instances of the following classes:
|
||||||
|
// >
|
||||||
|
// > NSATSTypesetter, NSColorSpace, NSFont, NSFontManager, NSFontPanel, NSImage, NSMenuView,
|
||||||
|
// > NSParagraphStyle, NSSimpleHorizontalTypesetter, NSTableCellView, NSTextView, NSViewController,
|
||||||
|
// > NSWindow, and NSWindowController.
|
||||||
|
// >
|
||||||
|
// > In addition, in OS X no classes in the AV Foundation framework support weak references.
|
||||||
|
//
|
||||||
|
// NSMenuView is deprecated (and not available to 64-bit applications).
|
||||||
|
// NSSimpleHorizontalTypesetter is an internal class.
|
||||||
|
|
||||||
|
if ([delegate isKindOfClass:[NSATSTypesetter class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSColorSpace class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSFont class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSFontManager class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSFontPanel class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSImage class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSParagraphStyle class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSTableCellView class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSTextView class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSViewController class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSWindow class]]) return NO;
|
||||||
|
if ([delegate isKindOfClass:[NSWindowController class]]) return NO;
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- (id)initWithDelegate:(id)inDelegate delegateQueue:(dispatch_queue_t)inDelegateQueue
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
{
|
||||||
|
if (SupportsWeakReferences(inDelegate))
|
||||||
|
{
|
||||||
|
delegate = inDelegate;
|
||||||
|
delegateQueue = inDelegateQueue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delegate = [NSNull null];
|
||||||
|
|
||||||
|
unsafeDelegate = inDelegate;
|
||||||
|
delegateQueue = inDelegateQueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
delegate = inDelegate;
|
||||||
|
delegateQueue = inDelegateQueue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !OS_OBJECT_USE_OBJC
|
||||||
|
if (delegateQueue)
|
||||||
|
dispatch_retain(delegateQueue);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
#if !OS_OBJECT_USE_OBJC
|
||||||
|
if (delegateQueue)
|
||||||
|
dispatch_release(delegateQueue);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#pragma mark -
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@implementation OIMGCDMulticastDelegateEnumerator
|
||||||
|
|
||||||
|
- (id)initFromDelegateNodes:(NSMutableArray *)inDelegateNodes
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
delegateNodes = [inDelegateNodes copy];
|
||||||
|
|
||||||
|
numNodes = [delegateNodes count];
|
||||||
|
currentNodeIndex = 0;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)count
|
||||||
|
{
|
||||||
|
return numNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)countOfClass:(Class)aClass
|
||||||
|
{
|
||||||
|
NSUInteger count = 0;
|
||||||
|
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate isKindOfClass:aClass])
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)countForSelector:(SEL)aSelector
|
||||||
|
{
|
||||||
|
NSUInteger count = 0;
|
||||||
|
|
||||||
|
for (OIMGCDMulticastDelegateNode *node in delegateNodes)
|
||||||
|
{
|
||||||
|
id nodeDelegate = node.delegate;
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate respondsToSelector:aSelector])
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)getNextDelegate:(id *)delPtr delegateQueue:(dispatch_queue_t *)dqPtr
|
||||||
|
{
|
||||||
|
while (currentNodeIndex < numNodes)
|
||||||
|
{
|
||||||
|
OIMGCDMulticastDelegateNode *node = delegateNodes[currentNodeIndex];
|
||||||
|
currentNodeIndex++;
|
||||||
|
|
||||||
|
id nodeDelegate = node.delegate; // snapshot atomic property
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (nodeDelegate)
|
||||||
|
{
|
||||||
|
if (delPtr) *delPtr = nodeDelegate;
|
||||||
|
if (dqPtr) *dqPtr = node.delegateQueue;
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)getNextDelegate:(id *)delPtr delegateQueue:(dispatch_queue_t *)dqPtr ofClass:(Class)aClass
|
||||||
|
{
|
||||||
|
while (currentNodeIndex < numNodes)
|
||||||
|
{
|
||||||
|
OIMGCDMulticastDelegateNode *node = delegateNodes[currentNodeIndex];
|
||||||
|
currentNodeIndex++;
|
||||||
|
|
||||||
|
id nodeDelegate = node.delegate; // snapshot atomic property
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate isKindOfClass:aClass])
|
||||||
|
{
|
||||||
|
if (delPtr) *delPtr = nodeDelegate;
|
||||||
|
if (dqPtr) *dqPtr = node.delegateQueue;
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)getNextDelegate:(id *)delPtr delegateQueue:(dispatch_queue_t *)dqPtr forSelector:(SEL)aSelector
|
||||||
|
{
|
||||||
|
while (currentNodeIndex < numNodes)
|
||||||
|
{
|
||||||
|
OIMGCDMulticastDelegateNode *node = delegateNodes[currentNodeIndex];
|
||||||
|
currentNodeIndex++;
|
||||||
|
|
||||||
|
id nodeDelegate = node.delegate; // snapshot atomic property
|
||||||
|
#if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE
|
||||||
|
if (nodeDelegate == [NSNull null])
|
||||||
|
nodeDelegate = node.unsafeDelegate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ([nodeDelegate respondsToSelector:aSelector])
|
||||||
|
{
|
||||||
|
if (delPtr) *delPtr = nodeDelegate;
|
||||||
|
if (dqPtr) *dqPtr = node.delegateQueue;
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Connection.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2021/2/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
#import "UploadFileCallbackProxy.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMInitConfig : NSObject
|
||||||
|
|
||||||
|
// Device type, default setting is based on userInterfaceIdiom for iPhone/iPad
|
||||||
|
@property (nonatomic, assign) OIMPlatform platform;
|
||||||
|
// SDK's API address
|
||||||
|
@property (nonatomic, copy) NSString *apiAddr;
|
||||||
|
// SDK's WebSocket address
|
||||||
|
@property (nonatomic, copy) NSString *wsAddr;
|
||||||
|
// Default is under Documents/
|
||||||
|
@property (nonatomic, copy, nullable) NSString *dataDir;
|
||||||
|
// Log level, default is 6
|
||||||
|
@property (nonatomic, assign) NSInteger logLevel;
|
||||||
|
// Compression, default is NO
|
||||||
|
@property (nonatomic, assign) BOOL compression;
|
||||||
|
// Log output to local, default is YES
|
||||||
|
@property (nonatomic, assign) BOOL isLogStandardOutput;
|
||||||
|
|
||||||
|
@property (nonatomic, copy, nullable) NSString *logFilePath;
|
||||||
|
|
||||||
|
// for log
|
||||||
|
@property (nonatomic, copy) NSString *systemType;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMManager (Connection)
|
||||||
|
|
||||||
|
- (BOOL)initSDKWithConfig:(OIMInitConfig *)config
|
||||||
|
onConnecting:(OIMVoidCallback)onConnecting
|
||||||
|
onConnectFailure:(OIMFailureCallback)onConnectFailure
|
||||||
|
onConnectSuccess:(OIMVoidCallback)onConnectSuccess
|
||||||
|
onKickedOffline:(OIMVoidCallback)onKickedOffline
|
||||||
|
onUserTokenExpired:(OIMVoidCallback)onUserTokenExpired
|
||||||
|
onUserTokenInvalid:(OIMStringCallback)onUserTokenInvalid;
|
||||||
|
|
||||||
|
- (void)unInitSDK;
|
||||||
|
|
||||||
|
- (void)uploadLogsWithProgress:(OIMUploadProgressCallback)onProgress
|
||||||
|
line:(NSInteger )line
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)logs:(NSString * _Nullable)file
|
||||||
|
line:(NSInteger)line
|
||||||
|
msgs:(NSString * _Nullable)msgs
|
||||||
|
err:(NSString * _Nullable)err
|
||||||
|
keyAndValues:(NSArray * _Nullable)keyAndValues
|
||||||
|
logLevel:(NSInteger )logLevel;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Connection.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2021/2/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+Connection.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@implementation OIMInitConfig
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
self.platform = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad ? iPad : iPhone;
|
||||||
|
self.dataDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingString:@"/"];
|
||||||
|
self.logFilePath = self.dataDir;
|
||||||
|
self.isLogStandardOutput = YES;
|
||||||
|
self.logLevel = 5;
|
||||||
|
self.compression = NO;
|
||||||
|
self.systemType = @"native_iOS";
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation OIMManager (Connection)
|
||||||
|
|
||||||
|
- (BOOL)initSDKWithConfig:(OIMInitConfig *)config
|
||||||
|
onConnecting:(OIMVoidCallback)onConnecting
|
||||||
|
onConnectFailure:(OIMFailureCallback)onConnectFailure
|
||||||
|
onConnectSuccess:(OIMVoidCallback)onConnectSuccess
|
||||||
|
onKickedOffline:(OIMVoidCallback)onKickedOffline
|
||||||
|
onUserTokenExpired:(OIMVoidCallback)onUserTokenExpired
|
||||||
|
onUserTokenInvalid:(OIMStringCallback)onUserTokenInvalid {
|
||||||
|
|
||||||
|
[self class].callbacker.connecting = onConnecting;
|
||||||
|
[self class].callbacker.connectFailure = onConnectFailure;
|
||||||
|
[self class].callbacker.connectSuccess = onConnectSuccess;
|
||||||
|
[self class].callbacker.kickedOffline = onKickedOffline;
|
||||||
|
[self class].callbacker.userTokenExpired = onUserTokenExpired;
|
||||||
|
[self class].callbacker.userTokenInvalid = onUserTokenInvalid;
|
||||||
|
|
||||||
|
NSMutableDictionary *param = [NSMutableDictionary new];
|
||||||
|
|
||||||
|
param[@"platformID"] = @(config.platform);
|
||||||
|
param[@"apiAddr"] = config.apiAddr;
|
||||||
|
param[@"wsAddr"] = config.wsAddr;
|
||||||
|
param[@"dataDir"] = config.dataDir;
|
||||||
|
param[@"logLevel"] = @(config.logLevel);
|
||||||
|
param[@"isCompression"] = @(config.compression);
|
||||||
|
param[@"logFilePath"] = config.logFilePath;
|
||||||
|
param[@"isLogStandardOutput"] = @(config.isLogStandardOutput);
|
||||||
|
param[@"systemType"] = config.systemType;
|
||||||
|
|
||||||
|
return Open_im_sdkInitSDK([self class].callbacker, [self operationId], param.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)unInitSDK {
|
||||||
|
Open_im_sdkUnInitSDK([self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadLogsWithProgress:(OIMUploadProgressCallback)onProgress
|
||||||
|
line:(NSInteger )line
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
UploadLogsCallbackProxy *progress = [[UploadLogsCallbackProxy alloc] initWithOnProgress:onProgress];
|
||||||
|
|
||||||
|
Open_im_sdkUploadLogs(callback, [self operationId], line, ex, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logs:(NSString *)file
|
||||||
|
line:(NSInteger)line
|
||||||
|
msgs:(NSString *)msgs
|
||||||
|
err:(NSString *)err
|
||||||
|
keyAndValues:(NSArray *)keyAndValues
|
||||||
|
logLevel:(NSInteger )logLevel {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
|
||||||
|
} onFailure:^(NSInteger code, NSString * _Nullable msg) {
|
||||||
|
|
||||||
|
}];
|
||||||
|
|
||||||
|
Open_im_sdkLogs(callback, [self operationId], logLevel, file ?: @"", line, msgs ?: @"", err ?: @"", (keyAndValues ?: @[]).mj_JSONString);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,192 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Conversation.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
#import "OIMConversationInfo.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMManager (Conversation)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of conversations
|
||||||
|
*/
|
||||||
|
- (void)getAllConversationListWithOnSuccess:(nullable OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a paginated list of conversations
|
||||||
|
* @param offset Starting offset
|
||||||
|
* @param count Number of conversations to fetch
|
||||||
|
*/
|
||||||
|
- (void)getConversationListSplitWithOffset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
onSuccess:(nullable OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a conversation; it will be automatically created if it doesn't exist
|
||||||
|
* @param sessionType Type of the conversation, 1 for one-on-one, 2 for group
|
||||||
|
* @param sourceID User ID for one-on-one or group ID for group
|
||||||
|
*/
|
||||||
|
- (void)getOneConversationWithSessionType:(OIMConversationType)sessionType
|
||||||
|
sourceID:(NSString *)sourceID
|
||||||
|
onSuccess:(nullable OIMConversationInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get multiple conversation lists
|
||||||
|
* @param conversationIDs List of conversation IDs
|
||||||
|
*/
|
||||||
|
- (void)getMultipleConversation:(NSArray <NSString *> *)conversationIDs
|
||||||
|
onSuccess:(nullable OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (NSString *)getConversationIDBySessionType:(OIMConversationType)sessionType
|
||||||
|
sourceID:(NSString *)sourceID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a conversation locally
|
||||||
|
* @param conversationID Conversation ID
|
||||||
|
*/
|
||||||
|
- (void)deleteConversationAndDeleteAllMsg:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a conversation both locally and on the server
|
||||||
|
* @param conversationID Conversation ID
|
||||||
|
*/
|
||||||
|
- (void)clearConversationAndDeleteAllMsg:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all conversations
|
||||||
|
*/
|
||||||
|
- (void)deleteAllConversationFromLocalWithOnSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure __attribute__((deprecated("Use hideAllConversations instead")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the draft for a conversation
|
||||||
|
* @param conversationID Conversation ID
|
||||||
|
* @param draftText Draft text; if it's "", the draft will be deleted
|
||||||
|
*/
|
||||||
|
- (void)setConversationDraft:(NSString *)conversationID
|
||||||
|
draftText:(NSString *)draftText
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pin or unpin a conversation
|
||||||
|
* @param conversationID Conversation ID
|
||||||
|
* @param isPinned If YES, the conversation will be pinned; if NO, it will be unpinned
|
||||||
|
*/
|
||||||
|
- (void)pinConversation:(NSString *)conversationID
|
||||||
|
isPinned:(BOOL)isPinned
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total number of unread messages
|
||||||
|
*/
|
||||||
|
- (void)getTotalUnreadMsgCountWithOnSuccess:(nullable OIMNumberCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the "do not disturb" status for a conversation
|
||||||
|
*/
|
||||||
|
- (void)setConversationRecvMessageOpt:(NSString *)conversationID
|
||||||
|
status:(OIMReceiveMessageOpt)status
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set private chat mode, can be used for "self-destructing" messages
|
||||||
|
*/
|
||||||
|
- (void)setConversationPrivateChat:(NSString *)conversationID
|
||||||
|
isPrivate:(BOOL)isPrivate
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set private chat mode with a self-destruct timer
|
||||||
|
*/
|
||||||
|
- (void)setConversationBurnDuration:(NSString *)conversationID
|
||||||
|
duration:(NSInteger)burnDuration
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the at symbol for a conversation
|
||||||
|
*/
|
||||||
|
- (void)resetConversationGroupAtType:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide a conversation without deleting chat history;
|
||||||
|
* If new messages arrive, the conversation will reappear.
|
||||||
|
*/
|
||||||
|
- (void)hideConversation:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)hideAllConversationsWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear unread messages
|
||||||
|
*/
|
||||||
|
- (void)markConversationMessageAsRead:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)setConversationEx:(NSString *)conversationID
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search sessions based on session name.
|
||||||
|
*/
|
||||||
|
- (void)searchConversation:(NSString *)name
|
||||||
|
onSuccess:(nullable OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typing status for one-on-one chat
|
||||||
|
*
|
||||||
|
* @param conversationID Receiver's ID
|
||||||
|
* @param focus Customized tip message
|
||||||
|
*/
|
||||||
|
- (void)changeInputStates:(NSString *)conversationID
|
||||||
|
focus:(BOOL)focus
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typing status for one-on-one chat
|
||||||
|
*
|
||||||
|
* @param conversationID Conversation's ID
|
||||||
|
* @param userID User's ID
|
||||||
|
*/
|
||||||
|
- (void)getInputstates:(NSString *)conversationID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
onSuccess:(nullable OIMInputStatusChangedCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param req OIMConversationReq
|
||||||
|
*/
|
||||||
|
- (void)setConversation:(NSString *)conversationID
|
||||||
|
req:(NSDictionary *)req
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Conversation.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+Conversation.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
#import "OIMConversationInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMManager (Conversation)
|
||||||
|
|
||||||
|
- (void)getAllConversationListWithOnSuccess:(OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMConversationInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetAllConversationList(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getConversationListSplitWithOffset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
onSuccess:(OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMConversationInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetConversationListSplit(callback, [self operationId], offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getOneConversationWithSessionType:(OIMConversationType)sessionType
|
||||||
|
sourceID:(NSString *)sourceID
|
||||||
|
onSuccess:(OIMConversationInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMConversationInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetOneConversation(callback, [self operationId], (int32_t)sessionType, sourceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getConversationIDBySessionType:(OIMConversationType)sessionType
|
||||||
|
sourceID:(NSString *)sourceID {
|
||||||
|
return Open_im_sdkGetConversationIDBySessionType([self operationId], sourceID, sessionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getMultipleConversation:(NSArray<NSString *> *)conversationIDs
|
||||||
|
onSuccess:(OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMConversationInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetMultipleConversation(callback, [self operationId], conversationIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteConversationAndDeleteAllMsg:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDeleteConversationAndDeleteAllMsg(callback, [self operationId], conversationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)clearConversationAndDeleteAllMsg:(NSString *)conversationID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkClearConversationAndDeleteAllMsg(callback, [self operationId], conversationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteAllConversationFromLocalWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversationDraft:(NSString *)conversationID
|
||||||
|
draftText:(NSString *)draftText
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetConversationDraft(callback, [self operationId], conversationID, draftText);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)pinConversation:(NSString *)conversationID
|
||||||
|
isPinned:(BOOL)isPinned
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setConversation:conversationID req:@{@"isPinned": @(isPinned)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getTotalUnreadMsgCountWithOnSuccess:(OIMNumberCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(data.integerValue);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetTotalUnreadMsgCount(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversationRecvMessageOpt:(NSString *)conversationID
|
||||||
|
status:(OIMReceiveMessageOpt)status
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setConversation:conversationID req:@{@"recvMsgOpt": @(status)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversationPrivateChat:(NSString *)conversationID
|
||||||
|
isPrivate:(BOOL)isPrivate
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setConversation:conversationID req:@{@"isPrivateChat": @(isPrivate)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversationBurnDuration:(NSString *)conversationID
|
||||||
|
duration:(NSInteger)burnDuration
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setConversation:conversationID req:@{@"burnDuration": @(burnDuration)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)resetConversationGroupAtType:(NSString *)conversationID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setConversation:conversationID req:@{@"groupAtType": @0} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hideConversation:(NSString *)conversationID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkHideConversation(callback, [self operationId], conversationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hideAllConversationsWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkHideAllConversations(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)markConversationMessageAsRead:(NSString *)conversationID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkMarkConversationMessageAsRead(callback, [self operationId], conversationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversationEx:(NSString *)conversationID
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setConversation:conversationID req:@{@"ex": ex} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)searchConversation:(NSString *)name
|
||||||
|
onSuccess:(nullable OIMConversationsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMConversationInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSearchConversation(callback, [self operationId], name);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)changeInputStates:(NSString *)conversationID
|
||||||
|
focus:(BOOL)focus
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkChangeInputStates(callback, [self operationId], conversationID, focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getInputstates:(NSString *)conversationID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
onSuccess:(OIMInputStatusChangedCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(data.mj_JSONObject);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetInputStates(callback, [self operationId], conversationID, userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setConversation:(NSString *)conversationID
|
||||||
|
req:(NSDictionary *)req
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetConversation(callback, [self operationId], conversationID, req.mj_JSONString);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Friend.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
#import "OIMUpdateFriendsReq.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMManager (Friend)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a friend
|
||||||
|
*
|
||||||
|
* @param userID User ID of the other person
|
||||||
|
* @param reqMessage Request message
|
||||||
|
*/
|
||||||
|
- (void)addFriend:(NSString *)userID
|
||||||
|
reqMessage:(NSString * _Nullable)reqMessage
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get received friend applications, i.e., people who have applied to be friends with me
|
||||||
|
*/
|
||||||
|
- (void)getFriendApplicationListAsRecipientWithOnSuccess:(nullable OIMFriendApplicationsCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friend applications sent by the current user
|
||||||
|
*/
|
||||||
|
- (void)getFriendApplicationListAsApplicantWithOnSuccess:(nullable OIMFriendApplicationsCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept a friend application from someone
|
||||||
|
* @param userID User ID
|
||||||
|
*/
|
||||||
|
- (void)acceptFriendApplication:(NSString *)userID
|
||||||
|
handleMsg:(NSString *)msg
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject a friend application
|
||||||
|
*
|
||||||
|
* @param userID User ID
|
||||||
|
*/
|
||||||
|
- (void)refuseFriendApplication:(NSString *)userID
|
||||||
|
handleMsg:(NSString *)msg
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add to the blacklist
|
||||||
|
*
|
||||||
|
* @param userID User ID
|
||||||
|
*/
|
||||||
|
- (void)addToBlackList:(NSString *)userID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)addToBlackList:(NSString *)userID
|
||||||
|
ex:(NSString * _Nullable)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
/**
|
||||||
|
* Blacklist
|
||||||
|
*/
|
||||||
|
- (void)getBlackListWithOnSuccess:(nullable OIMBlacksInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove from the blacklist
|
||||||
|
*
|
||||||
|
* @param userID User ID
|
||||||
|
*/
|
||||||
|
- (void)removeFromBlackList:(NSString *)userID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get related information for a specified list of friends
|
||||||
|
*
|
||||||
|
* @param usersID List of user IDs
|
||||||
|
*/
|
||||||
|
- (void)getSpecifiedFriendsInfo:(NSArray <NSString *> *)usersID
|
||||||
|
filterBlack:(BOOL)filterBlack
|
||||||
|
onSuccess:(nullable OIMFriendsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information for all friends
|
||||||
|
*/
|
||||||
|
- (void)getFriendListWithFilterBlack:(BOOL)filterBlack
|
||||||
|
onSuccess:(nullable OIMFriendsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)getFriendListPageWithOffset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
filterBlack:(BOOL)filterBlack
|
||||||
|
onSuccess:(nullable OIMFriendsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there is a friend relationship, i.e., if the user is in the friend list of the logged-in user. Note: Friendship is a two-way relationship.
|
||||||
|
* A result of 1 means the user is a friend (and not in the blacklist).
|
||||||
|
*
|
||||||
|
* @param usersID User ID list
|
||||||
|
*/
|
||||||
|
- (void)checkFriend:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(nullable OIMSimpleResultsCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a friend's remark
|
||||||
|
*
|
||||||
|
* @param uid User ID
|
||||||
|
* @param remark Remark information
|
||||||
|
*/
|
||||||
|
- (void)setFriendRemark:(NSString *)uid
|
||||||
|
remark:(NSString * _Nullable)remark
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a friend; friendship is a two-way relationship, this function only deletes the user's own friend
|
||||||
|
*
|
||||||
|
* @param friendUserID Friend's ID
|
||||||
|
*/
|
||||||
|
- (void)deleteFriend:(NSString *)friendUserID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local friend search
|
||||||
|
*/
|
||||||
|
- (void)searchFriends:(OIMSearchFriendsParam *)searchParam
|
||||||
|
onSuccess:(nullable OIMSearchUsersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)setFriendsEx:(NSArray<NSString *> *)friendIDs
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
|
||||||
|
- (void)updateFriends:(OIMUpdateFriendsReq *)req
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Friend.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+Friend.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@implementation OIMManager (Friend)
|
||||||
|
|
||||||
|
- (void)addFriend:(NSString *)userID
|
||||||
|
reqMessage:(NSString *)reqMessage
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
NSDictionary *param = @{@"toUserID": userID, @"reqMsg": reqMessage ?: @""};
|
||||||
|
Open_im_sdkAddFriend(callback, [self operationId], param.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getFriendApplicationListAsRecipientWithOnSuccess:(OIMFriendApplicationsCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMFriendApplication mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
|
||||||
|
Open_im_sdkGetFriendApplicationListAsRecipient(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getFriendApplicationListAsApplicantWithOnSuccess:(OIMFriendApplicationsCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMFriendApplication mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetFriendApplicationListAsApplicant(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)acceptFriendApplication:(NSString *)userID
|
||||||
|
handleMsg:(NSString *)msg
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
NSDictionary *param = @{@"toUserID": userID, @"handleMsg": msg ?: @""};
|
||||||
|
Open_im_sdkAcceptFriendApplication(callback, [self operationId], param.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)refuseFriendApplication:(NSString *)userID
|
||||||
|
handleMsg:(NSString *)msg
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
NSDictionary *param = @{@"toUserID": userID, @"handleMsg": msg ?: @""};
|
||||||
|
Open_im_sdkRefuseFriendApplication(callback, [self operationId], param.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addToBlackList:(NSString *)userID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
[self addToBlackList:userID ex:nil onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addToBlackList:(NSString *)userID
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkAddBlack(callback, [self operationId], userID, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getBlackListWithOnSuccess:(OIMBlacksInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMBlackInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetBlackList(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeFromBlackList:(NSString *)userID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkRemoveBlack(callback, [self operationId], userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getSpecifiedFriendsInfo:(NSArray <NSString *> *)usersID
|
||||||
|
filterBlack:(BOOL)filterBlack
|
||||||
|
onSuccess:(nullable OIMFriendsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMFriendInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetSpecifiedFriendsInfo(callback, [self operationId], usersID.mj_JSONString, filterBlack);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getFriendListWithFilterBlack:(BOOL)filterBlack
|
||||||
|
onSuccess:(nullable OIMFriendsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMFriendInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetFriendList(callback, [self operationId], filterBlack);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getFriendListPageWithOffset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
filterBlack:(BOOL)filterBlack
|
||||||
|
onSuccess:(OIMFriendsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMFriendInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetFriendListPage(callback, [self operationId], (int32_t)offset, (int32_t)count, filterBlack);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkFriend:(NSArray<NSString *> *)usersID
|
||||||
|
onSuccess:(OIMSimpleResultsCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMSimpleResultInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkCheckFriend(callback, [self operationId], usersID.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setFriendRemark:(NSString *)userID
|
||||||
|
remark:(NSString *)remark
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
OIMUpdateFriendsReq *req = [OIMUpdateFriendsReq new];
|
||||||
|
req.friendUserIDs = @[userID];
|
||||||
|
req.remark = remark;
|
||||||
|
|
||||||
|
[self updateFriends:req onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteFriend:(NSString *)friendUserID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDeleteFriend(callback, [self operationId], friendUserID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)searchFriends:(OIMSearchFriendsParam *)searchParam
|
||||||
|
onSuccess:(nullable OIMSearchUsersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
assert(searchParam.isSearchRemark || searchParam.isSearchNickname || searchParam.isSearchUserID);
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMSearchFriendsInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSearchFriends(callback, [self operationId], searchParam.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setFriendsEx:(NSArray<NSString *> *)friendIDs
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
OIMUpdateFriendsReq *req = [OIMUpdateFriendsReq new];
|
||||||
|
req.friendUserIDs = friendIDs;
|
||||||
|
req.ex = ex;
|
||||||
|
|
||||||
|
[self updateFriends:req onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateFriends:(OIMUpdateFriendsReq *)req
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkUpdateFriends(callback, [self operationId], req.mj_JSONString);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,317 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Group.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMManager (Group)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a group
|
||||||
|
*/
|
||||||
|
- (void)createGroup:(OIMGroupCreateInfo *)groupBaseInfo
|
||||||
|
onSuccess:(nullable OIMGroupInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply to join a group
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param reqMsg Request message for joining the group
|
||||||
|
* @param joinSource Method of joining
|
||||||
|
*/
|
||||||
|
- (void)joinGroup:(NSString *)groupID
|
||||||
|
reqMsg:(NSString * _Nullable)reqMsg
|
||||||
|
joinSource:(OIMJoinType)joinSource
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)joinGroup:(NSString *)groupID
|
||||||
|
reqMsg:(NSString *)reqMsg
|
||||||
|
joinSource:(OIMJoinType)joinSource
|
||||||
|
ex:(NSString * _Nullable)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quit a group
|
||||||
|
*/
|
||||||
|
- (void)quitGroup:(NSString *)groupID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of joined groups
|
||||||
|
*/
|
||||||
|
- (void)getJoinedGroupListWithOnSuccess:(nullable OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)getJoinedGroupListPageWithOffset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
onSuccess:(nullable OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch get group information
|
||||||
|
*
|
||||||
|
* @param groupsID Group ID collection
|
||||||
|
*/
|
||||||
|
- (void)getSpecifiedGroupsInfo:(NSArray <NSString *> *)groupsID
|
||||||
|
onSuccess:(nullable OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or update group information
|
||||||
|
*/
|
||||||
|
- (void)setGroupInfo:(OIMGroupInfo *)groupInfo
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)setGroupInfoDictionary:(NSDictionary *)groupInfo
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get group members
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param filter Member filter, 0 for no filter, 1 for group creator, 2 for administrator; default value is 0
|
||||||
|
* @param offset Starting offset
|
||||||
|
* @param count Member count
|
||||||
|
*/
|
||||||
|
- (void)getGroupMemberList:(NSString *)groupID
|
||||||
|
filter:(OIMGroupMemberFilter)filter
|
||||||
|
offset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
onSuccess:(nullable OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of specified group members
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param usersID Group member IDs
|
||||||
|
*/
|
||||||
|
- (void)getSpecifiedGroupMembersInfo:(NSString *)groupID
|
||||||
|
usersID:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(nullable OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove members from a group
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param reason Reason for removal
|
||||||
|
* @param usersID List of user IDs to be removed from the group
|
||||||
|
*/
|
||||||
|
- (void)kickGroupMember:(NSString *)groupID
|
||||||
|
reason:(NSString * _Nullable)reason
|
||||||
|
usersID:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer group ownership, only the group owner can perform this action
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param userID New group owner's user ID
|
||||||
|
*/
|
||||||
|
- (void)transferGroupOwner:(NSString *)groupID
|
||||||
|
newOwner:(NSString *)userID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invite certain people to join a group; all group members can perform this action
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param usersID List of user IDs to be invited
|
||||||
|
* @param reason Invitation message
|
||||||
|
*/
|
||||||
|
- (void)inviteUserToGroup:(NSString *)groupID
|
||||||
|
reason:(NSString *)reason
|
||||||
|
usersID:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of group member applications received by administrators or group owners
|
||||||
|
*/
|
||||||
|
- (void)getGroupApplicationListAsRecipientWithOnSuccess:(nullable OIMGroupsApplicationCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group applications sent by the current user
|
||||||
|
*/
|
||||||
|
- (void)getGroupApplicationListAsApplicantWithOnSuccess:(nullable OIMGroupsApplicationCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept someone's application to join a group as an administrator or group owner
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param fromUserID User ID of the user applying to join the group
|
||||||
|
* @param handleMsg Handling message
|
||||||
|
*/
|
||||||
|
- (void)acceptGroupApplication:(NSString *)groupID
|
||||||
|
fromUserId:(NSString *)fromUserID
|
||||||
|
handleMsg:(NSString * _Nullable)handleMsg
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reject someone's application to join a group as an administrator or group owner
|
||||||
|
*
|
||||||
|
* @param groupId Group ID
|
||||||
|
* @param fromUserID User ID of the user applying to join the group
|
||||||
|
* @param handleMsg Handling message
|
||||||
|
*/
|
||||||
|
- (void)refuseGroupApplication:(NSString *)groupID
|
||||||
|
fromUserId:(NSString *)fromUserID
|
||||||
|
handleMsg:(NSString * _Nullable)handleMsg
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disband a group
|
||||||
|
* Disband a group
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
*/
|
||||||
|
- (void)dismissGroup:(NSString *)groupID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mute or unmute a group member, mutedSeconds is set to 0 for unmuting
|
||||||
|
*/
|
||||||
|
- (void)changeGroupMemberMute:(NSString *)groupID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
mutedSeconds:(NSInteger)mutedSeconds
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mute or unmute a group
|
||||||
|
*/
|
||||||
|
- (void)changeGroupMute:(NSString *)groupID
|
||||||
|
isMute:(BOOL)isMute
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for groups by group name or group ID
|
||||||
|
*/
|
||||||
|
- (void)searchGroups:(OIMSearchGroupParam *)searchParam
|
||||||
|
onSuccess:(nullable OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group member nickname
|
||||||
|
*/
|
||||||
|
- (void)setGroupMemberNickname:(NSString *)groupID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
groupNickname:(NSString * _Nullable)groupNickname
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group member role level
|
||||||
|
*/
|
||||||
|
- (void)setGroupMemberRoleLevel:(NSString *)groupID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
roleLevel:(OIMGroupMemberRole)roleLevel
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group member's info
|
||||||
|
* @param groupMemberInfo OIMSetGroupMemberInfo
|
||||||
|
*/
|
||||||
|
- (void)setGroupMemberInfo:(NSDictionary *)groupMemberInfo
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of group members based on join time
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param joinTimeBegin Start time for joining
|
||||||
|
* @param joinTimeEnd End time for joining
|
||||||
|
* @param offset Starting index
|
||||||
|
* @param count Total count
|
||||||
|
* @param filterUserIDList List of user IDs to filter
|
||||||
|
*/
|
||||||
|
- (void)getGroupMemberListByJoinTimeFilter:(NSString *)groupID
|
||||||
|
offset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
joinTimeBegin:(NSInteger)joinTimeBegin
|
||||||
|
joinTimeEnd:(NSInteger)joinTimeEnd
|
||||||
|
filterUserIDList:(NSArray <NSString *> *)filterUserIDList
|
||||||
|
onSuccess:(nullable OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set group verification option for joining
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param needVerification Joining settings
|
||||||
|
*/
|
||||||
|
- (void)setGroupVerification:(NSString *)groupID
|
||||||
|
needVerification:(OIMGroupVerificationType)needVerification
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of managers and owners
|
||||||
|
* @param groupID Group ID
|
||||||
|
*/
|
||||||
|
- (void)getGroupMemberOwnerAndAdmin:(NSString *)groupID
|
||||||
|
onSuccess:(nullable OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether group members can add each other as friends
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param rule 0: Default behavior, 1: Not allowed
|
||||||
|
*/
|
||||||
|
- (void)setGroupApplyMemberFriend:(NSString *)groupID
|
||||||
|
rule:(int32_t)rule
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View group member information
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param rule 0: Default behavior, 1: Not allowed
|
||||||
|
*/
|
||||||
|
- (void)setGroupLookMemberInfo:(NSString *)groupID
|
||||||
|
rule:(int32_t)rule
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search group members
|
||||||
|
*/
|
||||||
|
- (void)searchGroupMembers:(OIMSearchGroupMembersParam *)searchParam
|
||||||
|
onSuccess:(nullable OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user has joined the group
|
||||||
|
*/
|
||||||
|
- (void)isJoinedGroup:(NSString *)groupID
|
||||||
|
onSuccess:(nullable OIMBoolCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)getUsersInGroup:(NSString *)groupID
|
||||||
|
userIDs:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMStringArrayCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Group.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+Group.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@implementation OIMManager (Group)
|
||||||
|
|
||||||
|
- (void)createGroup:(OIMGroupCreateInfo *)groupCreateInfo
|
||||||
|
onSuccess:(OIMGroupInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkCreateGroup(callback, [self operationId], groupCreateInfo.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)joinGroup:(NSString *)groupID
|
||||||
|
reqMsg:(NSString *)reqMsg
|
||||||
|
joinSource:(OIMJoinType)joinSource
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkJoinGroup(callback, [self operationId], groupID, reqMsg ?: @"", joinSource, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)joinGroup:(NSString *)groupID
|
||||||
|
reqMsg:(NSString *)reqMsg
|
||||||
|
joinSource:(OIMJoinType)joinSource
|
||||||
|
ex:(NSString *)ex
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkJoinGroup(callback, [self operationId], groupID, reqMsg ?: @"", joinSource, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)quitGroup:(NSString *)groupID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkQuitGroup(callback, [self operationId], groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)getJoinedGroupListWithOnSuccess:(OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetJoinedGroupList(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getJoinedGroupListPageWithOffset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
onSuccess:(OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetJoinedGroupListPage(callback, [self operationId], (int32_t)offset, (int32_t)count);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getSpecifiedGroupsInfo:(NSArray <NSString *> *)groupsID
|
||||||
|
onSuccess:(nullable OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetSpecifiedGroupsInfo(callback, [self operationId], groupsID.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupInfo:(OIMGroupInfo *)groupInfo
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetGroupInfo(callback, [self operationId], groupInfo.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupInfoDictionary:(NSDictionary *)groupInfo
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetGroupInfo(callback, [self operationId], groupInfo.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getGroupMemberList:(NSString *)groupID
|
||||||
|
filter:(OIMGroupMemberFilter)filter
|
||||||
|
offset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
onSuccess:(OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupMemberInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetGroupMemberList(callback, [self operationId], groupID, (int32_t)filter, (int32_t)offset, (int32_t)count);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getSpecifiedGroupMembersInfo:(NSString *)groupID
|
||||||
|
usersID:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(nullable OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupMemberInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
|
||||||
|
Open_im_sdkGetSpecifiedGroupMembersInfo(callback, [self operationId], groupID, usersID.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kickGroupMember:(NSString *)groupID
|
||||||
|
reason:(NSString *)reason
|
||||||
|
usersID:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkKickGroupMember(callback, [self operationId], groupID, reason ?: @"", usersID.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)transferGroupOwner:(NSString *)groupID
|
||||||
|
newOwner:(NSString *)userID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkTransferGroupOwner(callback, [self operationId], groupID, userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)inviteUserToGroup:(NSString *)groupID
|
||||||
|
reason:(NSString *)reason
|
||||||
|
usersID:(NSArray <NSString *> *)usersID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkInviteUserToGroup(callback, [self operationId], groupID, reason ?: @"", usersID.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getGroupApplicationListAsRecipientWithOnSuccess:(OIMGroupsApplicationCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupApplicationInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetGroupApplicationListAsRecipient(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getGroupApplicationListAsApplicantWithOnSuccess:(OIMGroupsApplicationCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupApplicationInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetGroupApplicationListAsApplicant(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)acceptGroupApplication:(NSString *)groupID
|
||||||
|
fromUserId:(NSString *)fromUserID
|
||||||
|
handleMsg:(NSString *)handleMsg
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkAcceptGroupApplication(callback, [self operationId], groupID, fromUserID, handleMsg ?: @"");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)refuseGroupApplication:(NSString *)groupID
|
||||||
|
fromUserId:(NSString *)fromUserID
|
||||||
|
handleMsg:(NSString *)handleMsg
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkRefuseGroupApplication(callback, [self operationId], groupID, fromUserID, handleMsg ?: @"");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dismissGroup:(NSString *)groupID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDismissGroup(callback, [self operationId], groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)changeGroupMemberMute:(NSString *)groupID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
mutedSeconds:(NSInteger)mutedSeconds
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkChangeGroupMemberMute(callback, [self operationId], groupID, userID, mutedSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)changeGroupMute:(NSString *)groupID
|
||||||
|
isMute:(BOOL)isMute
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkChangeGroupMute(callback, [self operationId], groupID, isMute);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)searchGroups:(OIMSearchGroupParam *)searchParam
|
||||||
|
onSuccess:(OIMGroupsInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSearchGroups(callback, [self operationId], searchParam.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupMemberNickname:(NSString *)groupID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
groupNickname:(NSString *)groupNickname
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setGroupMemberInfo:@{@"groupID": groupID, @"userID": userID, @"nickname": groupNickname} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupMemberRoleLevel:(NSString *)groupID
|
||||||
|
userID:(NSString *)userID
|
||||||
|
roleLevel:(OIMGroupMemberRole)roleLevel
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setGroupMemberInfo:@{@"groupID": groupID, @"userID": userID, @"roleLevel": @(roleLevel)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupMemberInfo:(NSDictionary *)groupMemberInfo
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetGroupMemberInfo(callback, [self operationId], groupMemberInfo.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getGroupMemberListByJoinTimeFilter:(NSString *)groupID
|
||||||
|
offset:(NSInteger)offset
|
||||||
|
count:(NSInteger)count
|
||||||
|
joinTimeBegin:(NSInteger)joinTimeBegin
|
||||||
|
joinTimeEnd:(NSInteger)joinTimeEnd
|
||||||
|
filterUserIDList:(NSArray <NSString *> *)filterUserIDList
|
||||||
|
onSuccess:(OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupMemberInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetGroupMemberListByJoinTimeFilter(callback, [self operationId], groupID, (int32_t)offset, (int32_t)count, joinTimeBegin, joinTimeEnd, filterUserIDList.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupVerification:(NSString *)groupID
|
||||||
|
needVerification:(OIMGroupVerificationType)needVerification
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setGroupInfoDictionary:@{@"groupID": groupID, @"needVerification": @(needVerification)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getGroupMemberOwnerAndAdmin:(NSString *)groupID
|
||||||
|
onSuccess:(OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupMemberInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetGroupMemberOwnerAndAdmin(callback, [self operationId], groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupApplyMemberFriend:(NSString *)groupID
|
||||||
|
rule:(int32_t)rule
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setGroupInfoDictionary:@{@"groupID": groupID, @"applyMemberFriend": @(rule)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGroupLookMemberInfo:(NSString *)groupID
|
||||||
|
rule:(int32_t)rule
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self setGroupInfoDictionary:@{@"groupID": groupID, @"lookMemberInfo": @(rule)} onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)searchGroupMembers:(OIMSearchParam *)searchParam
|
||||||
|
onSuccess:(OIMGroupMembersInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGroupMemberInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSearchGroupMembers(callback, [self operationId], searchParam.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)isJoinedGroup:(NSString *)groupID
|
||||||
|
onSuccess:(OIMBoolCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([data isEqualToString:@"true"]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkIsJoinGroup(callback, [self operationId], groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getUsersInGroup:(NSString *)groupID
|
||||||
|
userIDs:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMStringArrayCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
NSArray<NSString *> *users = data.mj_JSONObject;
|
||||||
|
onSuccess(nil, users);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetUsersInGroup(callback, [self operationId], groupID, userIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Login.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMManager (Login)
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark - Login
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log in
|
||||||
|
*
|
||||||
|
* @param userID User ID
|
||||||
|
* The UID is obtained from your own business server.
|
||||||
|
* @param token User token
|
||||||
|
* The token needs to be obtained by the business server from the OpenIM server.
|
||||||
|
*/
|
||||||
|
- (void)login:(NSString *)userID
|
||||||
|
token:(NSString *)token
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get login status
|
||||||
|
*/
|
||||||
|
- (OIMLoginStatus)getLoginStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log out
|
||||||
|
*/
|
||||||
|
- (void)logoutWithOnSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Login.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+Login.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@implementation OIMManager (Login)
|
||||||
|
|
||||||
|
- (void)login:(NSString *)userID
|
||||||
|
token:(NSString *)token
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
|
||||||
|
self.token = token;
|
||||||
|
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(data);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
[[self class].callbacker setListener];
|
||||||
|
|
||||||
|
Open_im_sdkLogin(callback, [self operationId], userID, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMLoginStatus)getLoginStatus {
|
||||||
|
return Open_im_sdkGetLoginStatus([self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logoutWithOnSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkLogout(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,481 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Message.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
#import "UploadFileCallbackProxy.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMMessageInfo (extension)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether the message is sent by self.
|
||||||
|
*/
|
||||||
|
- (BOOL)isSelf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a text message.
|
||||||
|
*
|
||||||
|
* @param text Content
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createTextMessage:(NSString *)text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complement the use of createTextAtMessage, insert the "@all" flag at a specified position.
|
||||||
|
*/
|
||||||
|
+ (OIMAtInfo *)createAtAllFlag:(NSString *)displayText;
|
||||||
|
|
||||||
|
+ (NSString *)getAtAllTag;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an @ text message.
|
||||||
|
*
|
||||||
|
* @param text Content
|
||||||
|
* @param atUsersID User IDs to mention
|
||||||
|
* @param atUsersInfo User information in the group
|
||||||
|
* @param message Message to reference
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createTextAtMessage:(NSString *)text
|
||||||
|
atUsersID:(NSArray<NSString *> *)atUsersID
|
||||||
|
atUsersInfo:(NSArray<OIMAtInfo *> *)atUsersInfo
|
||||||
|
message:(OIMMessageInfo * _Nullable)message;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an @ all members text message.
|
||||||
|
*
|
||||||
|
* @param text Content
|
||||||
|
* @param displayText Display text, e.g., "@All members"
|
||||||
|
* @param message Message to reference
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createTextAtAllMessage:(NSString *)text
|
||||||
|
displayText:(NSString * _Nullable)displayText
|
||||||
|
message:(OIMMessageInfo * _Nullable)message;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an image message. (If you provided a data cache path during initSDK, you need to copy the image to that path. For example, if the path is "A", you should copy the image to "A/pic/a.png", and the imagePath should be "/pic/a.png").
|
||||||
|
*
|
||||||
|
* @param imagePath Relative path
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createImageMessage:(NSString *)imagePath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an image message.
|
||||||
|
*
|
||||||
|
* @param imagePath Absolute path
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createImageMessageFromFullPath:(NSString *)imagePath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an audio message. For example: upload your own audio file and then use the returned URL to send the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createImageMessageByURL:(NSString *)sourcePath
|
||||||
|
sourcePicture:(OIMPictureInfo *)source
|
||||||
|
bigPicture:(OIMPictureInfo *)big
|
||||||
|
snapshotPicture:(OIMPictureInfo *)snapshot;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a sound message. (If you provided a data cache path during initSDK, you need to copy the sound file to that path. For example, if the path is "A", you should copy the sound file to "A/voice/a.m4c", and the soundPath should be "/voice/a.m4c").
|
||||||
|
*
|
||||||
|
* @param soundPath Relative path
|
||||||
|
* @param duration Duration
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createSoundMessage:(NSString *)soundPath
|
||||||
|
duration:(NSInteger)duration;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a sound message.
|
||||||
|
*
|
||||||
|
* @param soundPath Absolute path
|
||||||
|
* @param duration Duration
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createSoundMessageFromFullPath:(NSString *)soundPath
|
||||||
|
duration:(NSInteger)duration;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an audio message. For example: upload your own audio file and then use the returned URL to send the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createSoundMessageByURL:(NSString *)fileURL
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
size:(NSInteger)size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a video message. (If you provided a data cache path during initSDK, you need to copy the video file to that path. For example, if the path is "A", you should copy the video file to "A/video/a.mp4", and the videoPath should be "/video/a.mp4").
|
||||||
|
*
|
||||||
|
* @param videoPath Relative video path
|
||||||
|
* @param videoType MIME type
|
||||||
|
* @param duration Duration
|
||||||
|
* @param snapshotPath Relative path of the snapshot
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createVideoMessage:(NSString *)videoPath
|
||||||
|
videoType:(NSString *)videoType
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
snapshotPath:(NSString *)snapshotPath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a video message.
|
||||||
|
*
|
||||||
|
* @param videoPath Absolute video path
|
||||||
|
* @param videoType MIME type
|
||||||
|
* @param duration Duration
|
||||||
|
* @param snapshotPath Absolute snapshot path
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createVideoMessageFromFullPath:(NSString *)videoPath
|
||||||
|
videoType:(NSString *)videoType
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
snapshotPath:(NSString *)snapshotPath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a video message. For example: upload your own video file and then use the returned URL to send the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createVideoMessageByURL:(NSString *)fileURL
|
||||||
|
videoType:(NSString * _Nullable)videoType
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
size:(NSInteger)size
|
||||||
|
snapshot:(NSString * _Nullable)snapshotURL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a file message. (If you provided a data cache path during initSDK, you need to copy the file to that path. For example, if the path is "A", you should copy the file to "A/file/a.txt", and the filePath should be "/file/a.txt").
|
||||||
|
*
|
||||||
|
* @param filePath Relative path
|
||||||
|
* @param fileName File name
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createFileMessage:(NSString *)filePath
|
||||||
|
fileName:(NSString *)fileName;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a file message.
|
||||||
|
* (If you provided a data cache path during initSDK, you need to copy the file to that path. For example, if the path is "A", you should copy the file to "A/file/a.txt", and the filePath should be "/file/a.txt").
|
||||||
|
*
|
||||||
|
* @param filePath Absolute path
|
||||||
|
* @param fileName File name
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createFileMessageFromFullPath:(NSString *)filePath
|
||||||
|
fileName:(NSString *)fileName;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a file message. For example: upload your own file and then use the returned URL to send the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createFileMessageByURL:(NSString *)fileURL
|
||||||
|
fileName:(NSString * _Nullable)fileName
|
||||||
|
size:(NSInteger)size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a merged message.
|
||||||
|
*
|
||||||
|
* @param title Title
|
||||||
|
* @param summaryList Summaries
|
||||||
|
* @param messageList Message list
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createMergeMessage:(NSArray <OIMMessageInfo *> *)messages
|
||||||
|
title:(NSString *)title
|
||||||
|
summaryList:(NSArray <NSString *> *)summaries;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a forwarded message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createForwardMessage:(OIMMessageInfo *)message;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a location message.
|
||||||
|
*
|
||||||
|
* @param description Description message
|
||||||
|
* @param latitude Latitude
|
||||||
|
* @param longitude Longitude
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createLocationMessage:(NSString *)description
|
||||||
|
latitude:(double)latitude
|
||||||
|
longitude:(double)longitude;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a quoted message.
|
||||||
|
*
|
||||||
|
* @param text Content
|
||||||
|
* @param message Message being quoted
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createQuoteMessage:(NSString *)text
|
||||||
|
message:(OIMMessageInfo *)message;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a business card message.
|
||||||
|
*
|
||||||
|
* @param content String
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createCardMessage:(OIMCardElem *)card;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a custom message.
|
||||||
|
*
|
||||||
|
* @param data JSON String
|
||||||
|
* @param extension JSON String
|
||||||
|
* @param description Description
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createCustomMessage:(NSString *)data
|
||||||
|
extension:(NSString * _Nullable)extension
|
||||||
|
description:(NSString * _Nullable)description;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an animated sticker message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createFaceMessageWithIndex:(NSInteger)index
|
||||||
|
data:(NSString *)dataStr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an advanced message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createAdvancedTextMessage:(NSString *)text
|
||||||
|
messageEntityList:(NSArray <OIMMessageEntity *> *)messageEntityList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an advanced quoted message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ (OIMMessageInfo *)createAdvancedQuoteMessage:(NSString *)text
|
||||||
|
message:(OIMMessageInfo *)message
|
||||||
|
messageEntityList:(NSArray <OIMMessageEntity *> *)messageEntityList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMManager (Message)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message
|
||||||
|
*
|
||||||
|
* @param message The message body created with Create...Message methods (OIMMessageInfo)
|
||||||
|
* @param recvID User ID for one-on-one chat, or an empty string for group chat
|
||||||
|
* @param groupID Group ID for group chat, or an empty string for one-on-one chat
|
||||||
|
* @param offlinePushInfo Offline push information for the message (OIMOfflinePushInfo)
|
||||||
|
* @param isOnlineOnly Whether to send only online messages.
|
||||||
|
*/
|
||||||
|
- (void)sendMessage:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString * _Nullable)recvID
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
isOnlineOnly:(BOOL)isOnlineOnly
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo * _Nullable)offlinePushInfo
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(nullable OIMNumberCallback)onProgress
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)sendMessage:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString * _Nullable)recvID
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo * _Nullable)offlinePushInfo
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(nullable OIMNumberCallback)onProgress
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message without uploading multimedia files through the built-in SDK Object Storage Service (OSS)
|
||||||
|
*
|
||||||
|
* @param message The message body created with Create...Message methods (OIMMessageInfo)
|
||||||
|
* @param recvID User ID for one-on-one chat, or an empty string for group chat
|
||||||
|
* @param groupID Group ID for group chat, or an empty string for one-on-one chat
|
||||||
|
* @param offlinePushInfo Offline push information for the message (OIMOfflinePushInfo)
|
||||||
|
* @param isOnlineOnly Whether to send only online messages.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- (void)sendMessageNotOss:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString * _Nullable)recvID
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
isOnlineOnly:(BOOL)isOnlineOnly
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo * _Nullable)offlinePushInfo
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(nullable OIMNumberCallback)onProgress
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)sendMessageNotOss:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString * _Nullable)recvID
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo *)offlinePushInfo
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(nullable OIMNumberCallback)onProgress
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke a message
|
||||||
|
*
|
||||||
|
* @param conversationID Conversation ID
|
||||||
|
* @param clientMsgID Message ID
|
||||||
|
*/
|
||||||
|
- (void)revokeMessage:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typing status for one-on-one chat
|
||||||
|
*
|
||||||
|
* @param recvID Receiver's ID
|
||||||
|
* @param msgTip Customized tip message
|
||||||
|
*/
|
||||||
|
- (void)typingStatusUpdate:(NSString *)recvID
|
||||||
|
msgTip:(NSString *)msgTip
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark messages as read
|
||||||
|
*
|
||||||
|
* @param conversationID Conversation's ID
|
||||||
|
* @param clientMsgIDs ClientMsg's IDs
|
||||||
|
*/
|
||||||
|
- (void)markMessageAsReadByConID:(NSString *)conversationID
|
||||||
|
clientMsgIDs:(NSArray <NSString *> *)clientMsgIDs
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure __attribute__((deprecated("This method is deprecated. Use markConversationMessageAsRead instead.")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a message from local storage
|
||||||
|
*
|
||||||
|
* @param conversationID Conversation's ID
|
||||||
|
* @param clientMsgID ClientMsg's ID
|
||||||
|
*/
|
||||||
|
- (void)deleteMessageFromLocalStorage:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a message from local and server
|
||||||
|
*
|
||||||
|
* @param conversationID Conversation's ID
|
||||||
|
* @param clientMsgID ClientMsg's ID
|
||||||
|
*/
|
||||||
|
- (void)deleteMessage:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all messages from local storage
|
||||||
|
*/
|
||||||
|
- (void)deleteAllMsgFromLocalWithOnSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all messages from local and server
|
||||||
|
*/
|
||||||
|
- (void)deleteAllMsgFromLocalAndSvrWithOnSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a one-on-one chat message into local storage
|
||||||
|
*
|
||||||
|
* @param recvID Receiver's user ID
|
||||||
|
* @param sendID Sender's user ID
|
||||||
|
*/
|
||||||
|
- (void)insertSingleMessageToLocalStorage:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString *)recvID
|
||||||
|
sendID:(NSString *)sendID
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a group chat message into local storage
|
||||||
|
*
|
||||||
|
* @param groupID Group ID
|
||||||
|
* @param sendID Sender's user ID
|
||||||
|
*/
|
||||||
|
- (void)insertGroupMessageToLocalStorage:(OIMMessageInfo *)message
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
sendID:(NSString * _Nullable)sendID
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for local messages
|
||||||
|
*
|
||||||
|
* @param param search param
|
||||||
|
*/
|
||||||
|
- (void)searchLocalMessages:(OIMSearchParam *)param
|
||||||
|
onSuccess:(nullable OIMMessageSearchCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Independently upload a file to the initialized SDK's Object Storage Service (OSS) (Not needed for sending multimedia messages, as it is automatically done by the SDK internally)
|
||||||
|
*
|
||||||
|
* @param fullPath Absolute file path.
|
||||||
|
* @param name file's name
|
||||||
|
* @param cause file's catogery
|
||||||
|
*/
|
||||||
|
- (void)uploadFile:(NSString *)fullPath
|
||||||
|
name:(NSString * _Nullable)name
|
||||||
|
cause:(NSString * _Nullable)cause
|
||||||
|
onProgress:(OIMUploadProgressCallback)onProgress
|
||||||
|
onCompletion:(OIMUploadCompletionCallback)onCompletion
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set global message notification options
|
||||||
|
*
|
||||||
|
* @param opt receiving method.
|
||||||
|
*/
|
||||||
|
- (void)setGlobalRecvMessageOpt:(OIMReceiveMessageOpt)opt
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure __attribute__((deprecated("Use OIMManager+User: setSelfInfo instead")));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advanced Message Series Usage
|
||||||
|
*
|
||||||
|
* @param opts lastMinSeq is the value passed in the last pull callback, context, to be passed back in the second pull
|
||||||
|
*/
|
||||||
|
- (void)getAdvancedHistoryMessageList:(OIMGetAdvancedHistoryMessageListParam *)opts
|
||||||
|
onSuccess:(nullable OIMGetAdvancedHistoryMessageListCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advanced Message Series Usage
|
||||||
|
*
|
||||||
|
* @param opts lastMinSeq is the value passed in the last pull callback, context, to be passed back in the second pull
|
||||||
|
*/
|
||||||
|
- (void)getAdvancedHistoryMessageListReverse:(OIMGetAdvancedHistoryMessageListParam *)opts
|
||||||
|
onSuccess:(nullable OIMGetAdvancedHistoryMessageListCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a list of messages
|
||||||
|
*
|
||||||
|
* @param param Find parameters.
|
||||||
|
*/
|
||||||
|
- (void)findMessageList:(NSArray<OIMFindMessageListParam *> *)param
|
||||||
|
onSuccess:(nullable OIMMessageSearchCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the application badge count and inform the server of the current count
|
||||||
|
*
|
||||||
|
* @param count Number of corners.
|
||||||
|
*/
|
||||||
|
- (void)setAppBadge:(NSInteger)count
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For example, store the local state of a message
|
||||||
|
*
|
||||||
|
* @param conversationID Conversation's ID
|
||||||
|
* @param clientMsgID ClientMsg's ID
|
||||||
|
* @param localEx ex
|
||||||
|
*/
|
||||||
|
- (void)setMessageLocalEx:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
localEx: (NSString *)localEx
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,506 @@
|
||||||
|
//
|
||||||
|
// OIMManager+Message.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+Message.h"
|
||||||
|
#import "SendMessageCallbackProxy.h"
|
||||||
|
|
||||||
|
@implementation OIMMessageInfo (extension)
|
||||||
|
|
||||||
|
- (BOOL)isSelf {
|
||||||
|
return [self.sendID isEqualToString:[OIMManager.manager getLoginUserID]];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)convertToMessageInfo:(NSString *)json {
|
||||||
|
OIMMessageInfo *msg = [OIMMessageInfo mj_objectWithKeyValues:json];
|
||||||
|
msg.status = OIMMessageStatusUndefine;
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createTextMessage:(NSString *)text {
|
||||||
|
NSString *json = Open_im_sdkCreateTextMessage([OIMManager.manager operationId], text);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMAtInfo *)createAtAllFlag:(NSString *)displayText {
|
||||||
|
OIMAtInfo *all = [OIMAtInfo new];
|
||||||
|
all.atUserID = [self getAtAllTag];
|
||||||
|
all.groupNickname = displayText ?: @"Mention All";
|
||||||
|
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)getAtAllTag {
|
||||||
|
NSString *tag = Open_im_sdkGetAtAllTag([OIMManager.manager operationId]);
|
||||||
|
tag = [tag stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||||
|
tag = [tag stringByReplacingOccurrencesOfString:@"\\" withString:@""];
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createTextAtMessage:(NSString *)text
|
||||||
|
atUsersID:(NSArray<NSString *> *)atUsersID
|
||||||
|
atUsersInfo:(NSArray<OIMAtInfo *> *)atUsersInfo
|
||||||
|
message:(OIMMessageInfo *)message {
|
||||||
|
|
||||||
|
NSArray *atUsers = [OIMAtInfo mj_keyValuesArrayWithObjectArray:atUsersInfo];
|
||||||
|
NSString *atUsersJson = [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:atUsers options:0 error:nil] encoding:NSUTF8StringEncoding];
|
||||||
|
|
||||||
|
NSString *json = Open_im_sdkCreateTextAtMessage([OIMManager.manager operationId], text, atUsersID.mj_JSONString, atUsersJson, message ? message.mj_JSONString : @"");
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createTextAtAllMessage:(NSString *)text
|
||||||
|
displayText:(NSString *)displayText
|
||||||
|
message:(OIMMessageInfo * _Nullable)message {
|
||||||
|
NSString *json = Open_im_sdkCreateTextAtMessage([OIMManager.manager operationId], text, @[Open_im_sdkGetAtAllTag([[NSUUID UUID]UUIDString])].mj_JSONString, @[@{Open_im_sdkGetAtAllTag([[NSUUID UUID]UUIDString]): displayText ?: @"@all members"}].mj_JSONString, message ? message.mj_JSONString : @"");
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createImageMessage:(NSString *)imagePath {
|
||||||
|
NSString *json = Open_im_sdkCreateImageMessage([OIMManager.manager operationId], imagePath);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createImageMessageFromFullPath:(NSString *)imagePath {
|
||||||
|
NSString *json = Open_im_sdkCreateImageMessageFromFullPath([OIMManager.manager operationId], imagePath);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createImageMessageByURL:(NSString *)sourcePath
|
||||||
|
sourcePicture:(OIMPictureInfo *)source
|
||||||
|
bigPicture:(OIMPictureInfo *)big
|
||||||
|
snapshotPicture:(OIMPictureInfo *)snapshot {
|
||||||
|
|
||||||
|
NSString *json = Open_im_sdkCreateImageMessageByURL([OIMManager.manager operationId], sourcePath, source.mj_JSONString, big.mj_JSONString, snapshot.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createSoundMessage:(NSString *)soundPath
|
||||||
|
duration:(NSInteger)duration {
|
||||||
|
NSString *json = Open_im_sdkCreateSoundMessage([OIMManager.manager operationId], soundPath, duration);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createSoundMessageFromFullPath:(NSString *)soundPath
|
||||||
|
duration:(NSInteger)duration {
|
||||||
|
NSString *json = Open_im_sdkCreateSoundMessageFromFullPath([OIMManager.manager operationId], soundPath, duration);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createSoundMessageByURL:(NSString *)fileURL
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
size:(NSInteger)size {
|
||||||
|
OIMSoundElem *elem = [OIMSoundElem new];
|
||||||
|
elem.sourceUrl = fileURL;
|
||||||
|
elem.duration = duration;
|
||||||
|
elem.dataSize = size;
|
||||||
|
|
||||||
|
NSString *json = Open_im_sdkCreateSoundMessageByURL([OIMManager.manager operationId], elem.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createVideoMessage:(NSString *)videoPath
|
||||||
|
videoType:(NSString *)videoType
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
snapshotPath:(NSString *)snapshotPath {
|
||||||
|
NSString *json = Open_im_sdkCreateVideoMessage([OIMManager.manager operationId], videoPath, videoType, duration, snapshotPath);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createVideoMessageFromFullPath:(NSString *)videoPath
|
||||||
|
videoType:(NSString *)videoType
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
snapshotPath:(NSString *)snapshotPath {
|
||||||
|
NSString *json = Open_im_sdkCreateVideoMessageFromFullPath([OIMManager.manager operationId], videoPath, videoType, duration, snapshotPath);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createVideoMessageByURL:(NSString *)fileURL
|
||||||
|
videoType:(NSString *)videoType
|
||||||
|
duration:(NSInteger)duration
|
||||||
|
size:(NSInteger)size
|
||||||
|
snapshot:(NSString *)snapshotURL {
|
||||||
|
OIMVideoElem *elem = [OIMVideoElem new];
|
||||||
|
elem.videoUrl = fileURL;
|
||||||
|
elem.videoType = videoType;
|
||||||
|
elem.duration = duration;
|
||||||
|
elem.videoSize = size;
|
||||||
|
elem.snapshotUrl = snapshotURL;
|
||||||
|
|
||||||
|
NSString *json = Open_im_sdkCreateVideoMessageByURL([OIMManager.manager operationId], elem.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createFileMessage:(NSString *)filePath
|
||||||
|
fileName:(NSString *)fileName {
|
||||||
|
NSString *json = Open_im_sdkCreateFileMessage([OIMManager.manager operationId], filePath, fileName);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createFileMessageFromFullPath:(NSString *)filePath
|
||||||
|
fileName:(NSString *)fileName {
|
||||||
|
NSString *json = Open_im_sdkCreateFileMessageFromFullPath([OIMManager.manager operationId], filePath, fileName);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createFileMessageByURL:(NSString *)fileURL
|
||||||
|
fileName:(NSString *)fileName
|
||||||
|
size:(NSInteger)size {
|
||||||
|
OIMFileElem *elem = [OIMFileElem new];
|
||||||
|
elem.sourceUrl = fileURL;
|
||||||
|
elem.fileName = fileName ?: fileURL.lastPathComponent;
|
||||||
|
elem.fileSize = size;
|
||||||
|
|
||||||
|
NSString *json = Open_im_sdkCreateFileMessageByURL([OIMManager.manager operationId], elem.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createMergeMessage:(NSArray<OIMMessageInfo *> *)messages
|
||||||
|
title:(NSString *)title
|
||||||
|
summaryList:(NSArray<NSString *> *)summarys {
|
||||||
|
NSArray *msgs = [OIMMessageInfo mj_keyValuesArrayWithObjectArray:messages];
|
||||||
|
NSString *json = Open_im_sdkCreateMergerMessage([OIMManager.manager operationId], [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:msgs options:0 error:nil] encoding:NSUTF8StringEncoding], title, summarys.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createForwardMessage:(OIMMessageInfo *)message {
|
||||||
|
NSString *json = Open_im_sdkCreateForwardMessage([OIMManager.manager operationId], message.mj_JSONString);
|
||||||
|
|
||||||
|
return [OIMMessageInfo mj_objectWithKeyValues:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createLocationMessage:(NSString *)description
|
||||||
|
latitude:(double)latitude
|
||||||
|
longitude:(double)longitude {
|
||||||
|
NSString *json = Open_im_sdkCreateLocationMessage([OIMManager.manager operationId], description, longitude, latitude);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createQuoteMessage:(NSString *)text
|
||||||
|
message:(OIMMessageInfo *)message {
|
||||||
|
NSString *json = Open_im_sdkCreateQuoteMessage([OIMManager.manager operationId], text, message.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createCardMessage:(OIMCardElem *)card {
|
||||||
|
|
||||||
|
NSString *json = Open_im_sdkCreateCardMessage([OIMManager.manager operationId], card.mj_JSONString);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createCustomMessage:(NSString *)data
|
||||||
|
extension:(NSString *)extension
|
||||||
|
description:(NSString *)description {
|
||||||
|
NSString *json = Open_im_sdkCreateCustomMessage([OIMManager.manager operationId], data, extension, description);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createFaceMessageWithIndex:(NSInteger)index
|
||||||
|
data:(NSString *)dataStr {
|
||||||
|
NSString *json = Open_im_sdkCreateFaceMessage([OIMManager.manager operationId], index, dataStr);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createAdvancedTextMessage:(NSString *)text
|
||||||
|
messageEntityList:(NSArray<OIMMessageEntity *> *)messageEntityList {
|
||||||
|
NSArray *msgs = [OIMMessageEntity mj_keyValuesArrayWithObjectArray:messageEntityList];
|
||||||
|
NSString *json = Open_im_sdkCreateAdvancedTextMessage([OIMManager.manager operationId], text, [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:msgs options:0 error:nil] encoding:NSUTF8StringEncoding]);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMMessageInfo *)createAdvancedQuoteMessage:(NSString *)text
|
||||||
|
message:(OIMMessageInfo *)message
|
||||||
|
messageEntityList:(NSArray<OIMMessageEntity *> *)messageEntityList {
|
||||||
|
NSArray *msgs = [OIMMessageEntity mj_keyValuesArrayWithObjectArray:messageEntityList];
|
||||||
|
NSString *json = Open_im_sdkCreateAdvancedQuoteMessage([OIMManager.manager operationId], text, message.mj_JSONString, [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:msgs options:0 error:nil] encoding:NSUTF8StringEncoding]);
|
||||||
|
|
||||||
|
return [self convertToMessageInfo:json];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMManager (Message)
|
||||||
|
|
||||||
|
- (void)sendMessage:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString *)recvID
|
||||||
|
groupID:(NSString *)groupID
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo *)offlinePushInfo
|
||||||
|
onSuccess:(OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(OIMNumberCallback)onProgress
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
[self sendMessage:message
|
||||||
|
recvID:recvID
|
||||||
|
groupID:groupID
|
||||||
|
isOnlineOnly:false
|
||||||
|
offlinePushInfo:offlinePushInfo
|
||||||
|
onSuccess:onSuccess
|
||||||
|
onProgress:onProgress
|
||||||
|
onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sendMessage:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString * _Nullable)recvID
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
isOnlineOnly:(BOOL)isOnlineOnly
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo * _Nullable)offlinePushInfo
|
||||||
|
onSuccess:(nullable OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(nullable OIMNumberCallback)onProgress
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
assert(recvID.length != 0 || groupID.length != 0);
|
||||||
|
|
||||||
|
SendMessageCallbackProxy *callback = [[SendMessageCallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMMessageInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onProgress:onProgress onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSendMessage(callback, [self operationId], message.mj_JSONString, recvID ?: @"", groupID ?: @"", offlinePushInfo ? offlinePushInfo.mj_JSONString : @"{}", isOnlineOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sendMessageNotOss:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString *)recvID
|
||||||
|
groupID:(NSString *)groupID
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo *)offlinePushInfo
|
||||||
|
onSuccess:(OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(OIMNumberCallback)onProgress
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
assert(recvID.length != 0 || groupID.length != 0);
|
||||||
|
|
||||||
|
[self sendMessageNotOss:message
|
||||||
|
recvID:recvID
|
||||||
|
groupID:groupID
|
||||||
|
isOnlineOnly:false
|
||||||
|
offlinePushInfo:offlinePushInfo
|
||||||
|
onSuccess:onSuccess
|
||||||
|
onProgress:onProgress
|
||||||
|
onFailure:onFailure];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sendMessageNotOss:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString *)recvID
|
||||||
|
groupID:(NSString *)groupID
|
||||||
|
isOnlineOnly:(BOOL)isOnlineOnly
|
||||||
|
offlinePushInfo:(OIMOfflinePushInfo *)offlinePushInfo
|
||||||
|
onSuccess:(OIMMessageInfoCallback)onSuccess
|
||||||
|
onProgress:(OIMNumberCallback)onProgress
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
assert(recvID.length != 0 || groupID.length != 0);
|
||||||
|
|
||||||
|
SendMessageCallbackProxy *callback = [[SendMessageCallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMMessageInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onProgress:onProgress onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSendMessageNotOss(callback, [self operationId], message.mj_JSONString, recvID, groupID, offlinePushInfo.mj_JSONString, isOnlineOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)revokeMessage:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkRevokeMessage(callback, [self operationId], conversationID, clientMsgID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)typingStatusUpdate:(NSString *)recvID
|
||||||
|
msgTip:(NSString *)msgTip
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkTypingStatusUpdate(callback, [self operationId], recvID, msgTip);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)markMessageAsReadByConID:(NSString *)conversationID
|
||||||
|
clientMsgIDs:(NSArray <NSString *> *)clientMsgIDs
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkMarkMessagesAsReadByMsgID(callback, [self operationId], conversationID, clientMsgIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteMessage:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDeleteMessage(callback, [self operationId], conversationID, clientMsgID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteMessageFromLocalStorage:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDeleteMessageFromLocalStorage(callback, [self operationId], conversationID, clientMsgID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteAllMsgFromLocalWithOnSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDeleteAllMsgFromLocal(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteAllMsgFromLocalAndSvrWithOnSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkDeleteAllMsgFromLocalAndSvr(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)insertSingleMessageToLocalStorage:(OIMMessageInfo *)message
|
||||||
|
recvID:(NSString *)recvID
|
||||||
|
sendID:(NSString *)sendID
|
||||||
|
onSuccess:(OIMMessageInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMMessageInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkInsertSingleMessageToLocalStorage(callback, [self operationId], message.mj_JSONString, recvID, sendID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)insertGroupMessageToLocalStorage:(OIMMessageInfo *)message
|
||||||
|
groupID:(NSString *)groupID
|
||||||
|
sendID:(NSString *)sendID
|
||||||
|
onSuccess:(OIMMessageInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMMessageInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkInsertGroupMessageToLocalStorage(callback, [self operationId], message.mj_JSONString, groupID, sendID);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)searchLocalMessages:(OIMSearchParam *)param
|
||||||
|
onSuccess:(OIMMessageSearchCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMSearchResultInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSearchLocalMessages(callback, [self operationId], param.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadFile:(NSString *)fullPath
|
||||||
|
name:(NSString * _Nullable)name
|
||||||
|
cause:(NSString * _Nullable)cause
|
||||||
|
onProgress:(OIMUploadProgressCallback)onProgress
|
||||||
|
onCompletion:(OIMUploadCompletionCallback)onCompletion
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
UploadFileCallbackProxy *upload = [[UploadFileCallbackProxy alloc]initWithOnProgress:onProgress onCompletion:onCompletion];
|
||||||
|
|
||||||
|
NSDictionary *param = @{@"putID": fullPath.lastPathComponent,
|
||||||
|
@"name": name ?: fullPath.lastPathComponent,
|
||||||
|
@"filepath": fullPath,
|
||||||
|
@"cause": cause ?: @""};
|
||||||
|
|
||||||
|
Open_im_sdkUploadFile(callback, [self operationId], param.mj_JSONString, upload);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGlobalRecvMessageOpt:(OIMReceiveMessageOpt)opt
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getAdvancedHistoryMessageList:(OIMGetAdvancedHistoryMessageListParam *)opts
|
||||||
|
onSuccess:(OIMGetAdvancedHistoryMessageListCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGetAdvancedHistoryMessageListInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetAdvancedHistoryMessageList(callback, [self operationId], opts.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getAdvancedHistoryMessageListReverse:(OIMGetAdvancedHistoryMessageListParam *)opts
|
||||||
|
onSuccess:(nullable OIMGetAdvancedHistoryMessageListCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMGetAdvancedHistoryMessageListInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetAdvancedHistoryMessageListReverse(callback, [self operationId], opts.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)findMessageList:(NSArray<OIMFindMessageListParam *> *)param
|
||||||
|
onSuccess:(OIMMessageSearchCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMSearchResultInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
NSArray *params = [OIMFindMessageListParam mj_keyValuesArrayWithObjectArray:param];
|
||||||
|
|
||||||
|
Open_im_sdkFindMessageList(callback, [self operationId], params.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setAppBadge:(NSInteger)count
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetAppBadge(callback, [self operationId], (int32_t)count);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setMessageLocalEx:(NSString *)conversationID
|
||||||
|
clientMsgID:(NSString *)clientMsgID
|
||||||
|
localEx: (NSString *)localEx
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetMessageLocalEx(callback, [self operationId], conversationID, clientMsgID, localEx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
//
|
||||||
|
// OIMManager+User.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMManager (User)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch query user information by uid
|
||||||
|
*
|
||||||
|
* @param uids List of user IDs
|
||||||
|
*/
|
||||||
|
- (void)getUsersInfo:(NSArray <NSString *> *)uids
|
||||||
|
onSuccess:(nullable OIMPublicUsersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the information of the currently logged-in user
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
- (void)setSelfInfo:(OIMUserInfo *)userInfo
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information of the currently logged-in user
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
- (void)getSelfInfoWithOnSuccess:(nullable OIMUserInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update FCM token
|
||||||
|
* @param fcmToken FCM Token
|
||||||
|
* @param expireTime expire time, unit: s
|
||||||
|
*/
|
||||||
|
- (void)updateFcmToken:(NSString *)fcmToken
|
||||||
|
expireTime:(NSInteger)expireTime
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to the online status of users
|
||||||
|
*/
|
||||||
|
- (void)subscribeUsersStatus:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMUserStatusInfosCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from the online status of users
|
||||||
|
*/
|
||||||
|
- (void)unsubscribeUsersStatus:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the online status of all subscribed users
|
||||||
|
*/
|
||||||
|
- (void)getSubscribeUsersStatusWithOnSuccess:(nullable OIMUserStatusInfosCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user status for regular users
|
||||||
|
*/
|
||||||
|
- (void)getUserStatus:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMUserStatusInfosCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
- (void)getUsersInfoWithCache:(NSArray<NSString *> *)userIDs
|
||||||
|
groupID:(NSString * _Nullable)groupID
|
||||||
|
onSuccess:(nullable OIMPublicUsersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure __attribute__((deprecated("Use getUsersInfo instead")));
|
||||||
|
|
||||||
|
|
||||||
|
/// Global Do Not Disturb
|
||||||
|
/// [status] 0: Normal; 1: Do not accept messages; 2: Accept online messages but not offline messages;
|
||||||
|
- (void)setGlobalRecvMessageOpt:(NSInteger )status
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
//
|
||||||
|
// OIMManager+User.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager+User.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@implementation OIMManager (User)
|
||||||
|
|
||||||
|
- (void)getUsersInfo:(NSArray <NSString *> *)uids
|
||||||
|
onSuccess:(OIMPublicUsersInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMPublicUserInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetUsersInfo(callback, [self operationId], uids.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSelfInfo:(OIMUserInfo *)userInfo
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSetSelfInfo(callback, [self operationId], userInfo.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getSelfInfoWithOnSuccess:(OIMUserInfoCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMUserInfo mj_objectWithKeyValues:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetSelfUserInfo(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateFcmToken:(NSString *)fmcToken
|
||||||
|
expireTime:(NSInteger)expireTime
|
||||||
|
onSuccess:(OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkUpdateFcmToken(callback, [self operationId], fmcToken, expireTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)subscribeUsersStatus:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMUserStatusInfosCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMUserStatusInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkSubscribeUsersStatus(callback, [self operationId], userIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)unsubscribeUsersStatus:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:onSuccess onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkUnsubscribeUsersStatus(callback, [self operationId], userIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getSubscribeUsersStatusWithOnSuccess:(nullable OIMUserStatusInfosCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMUserStatusInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetSubscribeUsersStatus(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getUserStatus:(NSArray<NSString *> *)userIDs
|
||||||
|
onSuccess:(nullable OIMUserStatusInfosCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMUserStatusInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetUserStatus(callback, [self operationId], userIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getUsersInfoWithCache:(NSArray<NSString *> *)userIDs
|
||||||
|
groupID:(NSString *)groupID
|
||||||
|
onSuccess:(nullable OIMPublicUsersInfoCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess([OIMPublicUserInfo mj_objectArrayWithKeyValuesArray:data]);
|
||||||
|
}
|
||||||
|
} onFailure:onFailure];
|
||||||
|
|
||||||
|
Open_im_sdkGetUsersInfo(callback, [self operationId], userIDs.mj_JSONString);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setGlobalRecvMessageOpt:(NSInteger )status
|
||||||
|
onSuccess:(nullable OIMSuccessCallback)onSuccess
|
||||||
|
onFailure:(nullable OIMFailureCallback)onFailure {
|
||||||
|
OIMUserInfo *info = [OIMUserInfo new];
|
||||||
|
info.globalRecvMsgOpt = status;
|
||||||
|
|
||||||
|
[self setSelfInfo:info onSuccess:onSuccess onFailure:onFailure];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// OIMManager.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMCallbacker.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMManager : NSObject
|
||||||
|
|
||||||
|
+ (instancetype)manager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All listeners setup here (User, Friend, Group, Conversation, AdvancedMsg, etc.)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, strong, class, readonly) OIMManager *manager;
|
||||||
|
@property (nonatomic, strong, class, readonly) OIMCallbacker *callbacker;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *token;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *objectStorage;
|
||||||
|
/**
|
||||||
|
* SDK version number
|
||||||
|
*/
|
||||||
|
+ (NSString *)sdkSdkVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the login user's UID
|
||||||
|
*/
|
||||||
|
- (NSString *)getLoginUserID;
|
||||||
|
|
||||||
|
- (NSString *)operationId;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
//
|
||||||
|
// OIMManager.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMManager.h"
|
||||||
|
#import "OIMReachability.h"
|
||||||
|
#import "CallbackProxy.h"
|
||||||
|
|
||||||
|
@interface OIMManager ()
|
||||||
|
{
|
||||||
|
OIMCallbacker *_callbacker;
|
||||||
|
OIMReachability *internetReachability;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMManager
|
||||||
|
@dynamic callbacker;
|
||||||
|
|
||||||
|
+ (instancetype)manager {
|
||||||
|
|
||||||
|
static OIMManager *instance;
|
||||||
|
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
instance = [[OIMManager alloc]init];
|
||||||
|
});
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
if (self = [super init]) {
|
||||||
|
// This method will be called when the app enters the foreground from the background.
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(applicationWillEnterForeground:)
|
||||||
|
name:UIApplicationWillEnterForegroundNotification
|
||||||
|
object:nil];
|
||||||
|
//Add an observer to detect when the app enters the background
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(applicationDidEnterBackground:)
|
||||||
|
name:UIApplicationDidEnterBackgroundNotification
|
||||||
|
object:nil];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(reachabilityChanged:)
|
||||||
|
name:kReachabilityChangedNotification
|
||||||
|
object:nil];
|
||||||
|
|
||||||
|
internetReachability = [OIMReachability reachabilityForInternetConnection];
|
||||||
|
[internetReachability startNotifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (OIMCallbacker *)callbacker {
|
||||||
|
return [OIMManager manager].callbacker;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (OIMCallbacker *)callbacker {
|
||||||
|
if (_callbacker == nil) {
|
||||||
|
_callbacker = [OIMCallbacker callbacker];
|
||||||
|
}
|
||||||
|
return _callbacker;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)sdkSdkVersion
|
||||||
|
{
|
||||||
|
return Open_im_sdkGetSdkVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getLoginUserID {
|
||||||
|
return Open_im_sdkGetLoginUserID();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)operationId {
|
||||||
|
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0];
|
||||||
|
NSTimeInterval time = [date timeIntervalSince1970] * 1000;
|
||||||
|
return [NSString stringWithFormat:@"%ld", (NSInteger)time];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidEnterBackground:(NSNotification *)note {
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
|
||||||
|
} onFailure:^(NSInteger code, NSString * _Nullable msg) {
|
||||||
|
|
||||||
|
}];
|
||||||
|
|
||||||
|
Open_im_sdkSetAppBackgroundStatus(callback, [self operationId], YES);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillEnterForeground:(NSNotification *)note {
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
|
||||||
|
} onFailure:^(NSInteger code, NSString * _Nullable msg) {
|
||||||
|
|
||||||
|
}];
|
||||||
|
|
||||||
|
Open_im_sdkSetAppBackgroundStatus(callback, [self operationId], NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)reachabilityChanged:(NSNotification *)note {
|
||||||
|
OIMReachability *reachability = [note object];
|
||||||
|
NSParameterAssert([reachability isKindOfClass:[OIMReachability class]]);
|
||||||
|
|
||||||
|
CallbackProxy *callback = [[CallbackProxy alloc]initWithOnSuccess:^(NSString * _Nullable data) {
|
||||||
|
|
||||||
|
} onFailure:^(NSInteger code, NSString * _Nullable msg) {
|
||||||
|
|
||||||
|
}];
|
||||||
|
|
||||||
|
Open_im_sdkNetworkStatusChanged(callback, [self operationId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// OIMAtElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMQuoteElem.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMAtInfo : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the member being mentioned
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *atUserID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nickname or group nickname of the mentioned member
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupNickname;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMAtTextElem : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mentioned message content
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of user IDs being mentioned
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSArray<NSString *> *atUserList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of mentioned users
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSArray<OIMAtInfo *> *atUsersInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quoted message with @ mention
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong) OIMMessageInfo *quoteMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the sender is mentioned (@)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign, readonly) BOOL isAtSelf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether @ all members
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign, readonly) BOOL isAtAll;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// OIMAtElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMAtElem.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
@import OpenIMCore;
|
||||||
|
|
||||||
|
@implementation OIMAtInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMAtTextElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"atUsersInfo" : [OIMAtInfo class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isAtAll {
|
||||||
|
return self.atUserList.count > 0 &&
|
||||||
|
[self.atUserList.firstObject isKindOfClass:[NSString class]] &&
|
||||||
|
[self.atUserList.firstObject isEqualToString:Open_im_sdkGetAtAllTag([[NSUUID UUID]UUIDString])];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
//
|
||||||
|
// OIMAttachedInfoElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/3/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMMessageElem.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/// Users who have read the message
|
||||||
|
///
|
||||||
|
@interface OIMGroupHasReadInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSArray <NSString *> *hasReadUserIDList;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger hasReadCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of group members at the time of sending this message
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger groupMemberCount;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMUploadProgress : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger total;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger save;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger current;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMAttachedInfoElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMGroupHasReadInfo *groupHasReadInfo;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isPrivateChat;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval burnDuration;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval hasReadTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL notSenderNotificationPush;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSArray <OIMMessageEntity *> *messageEntityList;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isEncryption;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL inEncryptStatus;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) OIMUploadProgress *uploadProgress;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// OIMAttachedInfoElem.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/3/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMAttachedInfoElem.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
@implementation OIMGroupHasReadInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMUploadProgress
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMAttachedInfoElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"messageEntityList" : [OIMMessageEntity class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
//
|
||||||
|
// OIMConversationInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/// Conversation Information
|
||||||
|
///
|
||||||
|
@interface OIMConversationBaseInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *conversationID;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Conversation Information
|
||||||
|
///
|
||||||
|
@interface OIMConversationInfo : OIMConversationBaseInfo
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMConversationType conversationType;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *showName;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *faceURL;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMReceiveMessageOpt recvMsgOpt;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger unreadCount;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMGroupAtType groupAtType;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger latestMsgSendTime;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *draftText;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger draftTextTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isPinned;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether private chat (burn after reading) is enabled
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isPrivateChat;
|
||||||
|
/**
|
||||||
|
* Private chat duration
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSTimeInterval burnDuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether still in the group, return true if left the group
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isNotInGroup;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *attachedInfo;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMMessageInfo *latestMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Do Not Disturb Conversation Information
|
||||||
|
///
|
||||||
|
@interface OIMConversationNotDisturbInfo : OIMConversationBaseInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do Not Disturb Status
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) OIMReceiveMessageOpt result;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// input status Information
|
||||||
|
///
|
||||||
|
@interface OIMInputStatusChangedData : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *conversationID;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *userID;
|
||||||
|
// OIMPlatform
|
||||||
|
@property (nonatomic, copy) NSArray<NSNumber *> *platformIDs;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMConversationReq : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMReceiveMessageOpt recvMsgOpt;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isPinned;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMGroupAtType groupAtType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether private chat (burn after reading) is enabled
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isPrivateChat;
|
||||||
|
/**
|
||||||
|
* Private chat duration
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSTimeInterval burnDuration;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// OIMConversationInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMConversationInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMConversationBaseInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMConversationInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMConversationNotDisturbInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMInputStatusChangedData
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMConversationReq
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// OIMCustomElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMCustomElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *data;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *extension;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *description_;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// OIMCustomElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMCustomElem.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
@implementation OIMCustomElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
|
||||||
|
return @{@"description_" : @"description"};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// OIMFaceElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/3/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMFaceElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger index;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *data;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// OIMFaceElem.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/3/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMFaceElem.h"
|
||||||
|
|
||||||
|
@implementation OIMFaceElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// OIMFileElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMFileElem : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local resource address of the file
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *filePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UUID
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *uuID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OSS address
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *sourceUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File name
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *fileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File size
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger fileSize;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// OIMFileElem.m
|
||||||
|
// Open-IM-SDK-iOS
|
||||||
|
//
|
||||||
|
// Created by xpg on 2021/11/5.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMFileElem.h"
|
||||||
|
|
||||||
|
@implementation OIMFileElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// OIMFriendApplication.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/// Friend application information, indicating who is applying to add whom as a friend and the result of handling the application.
|
||||||
|
///
|
||||||
|
@interface OIMFriendApplication : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *fromUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *fromNickname;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *fromFaceURL;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *toUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *toNickname;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *toFaceURL;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMApplicationStatus handleResult;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *reqMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger createTime;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *handlerUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *handleMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger handleTime;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// OIMFriendApplication.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMFriendApplication.h"
|
||||||
|
|
||||||
|
@implementation OIMFriendApplication
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// OIMFullUserInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/// Public user information, mainly basic information, excluding other privacy fields such as phone number.
|
||||||
|
///
|
||||||
|
@interface OIMPublicUserInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *nickname;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *faceURL;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Blacklist information, basic information of users in the blacklist. Note that the blacklist is a mutual relationship.
|
||||||
|
///
|
||||||
|
@interface OIMBlackInfo : OIMPublicUserInfo
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger createTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger addSource;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *operatorUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *attachedInfo;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Friend information, basic information of users who are friends. Note that the blacklist is a mutual relationship.
|
||||||
|
///
|
||||||
|
@interface OIMFriendInfo : OIMPublicUserInfo
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ownerUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *remark;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger createTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger addSource;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *operatorUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *attachedInfo;
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMSearchFriendsInfo : OIMFriendInfo
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMRelationship relationship;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// OIMFullUserInfo.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMFullUserInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMPublicUserInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMBlackInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMFriendInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMSearchFriendsInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
// OIMGroupApplicationInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/// Group joining application information
|
||||||
|
///
|
||||||
|
@interface OIMGroupApplicationInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupName;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *notification;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *introduction;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupFaceURL;
|
||||||
|
@property (nonatomic, assign) NSInteger createTime;
|
||||||
|
@property (nonatomic, assign) NSInteger status;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *creatorUserID;
|
||||||
|
@property (nonatomic, assign) NSInteger groupType;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ownerUserID;
|
||||||
|
@property (nonatomic, assign) NSInteger memberCount;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *nickname;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userFaceURL;
|
||||||
|
@property (nonatomic, assign) OIMApplicationStatus handleResult;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *reqMsg;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *handledMsg;
|
||||||
|
@property (nonatomic, assign) NSInteger reqTime;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *handleUserID;
|
||||||
|
@property (nonatomic, assign) NSInteger handledTime;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *inviterUserID;
|
||||||
|
@property (nonatomic, assign) OIMJoinType joinSource;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// OIMGroupApplicationInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMGroupApplicationInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMGroupApplicationInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// OIMGroupInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMGroupBaseInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMGroupType groupType;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupName;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *notification;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *introduction;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *faceURL;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMGroupCreateInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, strong) OIMGroupBaseInfo *groupInfo;
|
||||||
|
@property (nonatomic, copy) NSArray <NSString *> *memberUserIDs;
|
||||||
|
@property (nonatomic, copy) NSArray <NSString *> *adminUserIDs;
|
||||||
|
@property (nonatomic, copy) NSString *ownerUserID;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Group Information
|
||||||
|
///
|
||||||
|
@interface OIMGroupInfo : OIMGroupBaseInfo
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
@property (nonatomic, assign, readonly) NSInteger createTime;
|
||||||
|
@property (nonatomic, assign, readonly) NSInteger memberCount;
|
||||||
|
@property (nonatomic, assign, readonly) OIMGroupStatus status;
|
||||||
|
@property (nonatomic, copy, readonly) NSString *creatorUserID;
|
||||||
|
@property (nonatomic, copy, readonly) NSString *ownerUserID;
|
||||||
|
@property (nonatomic, assign) OIMGroupVerificationType needVerification;
|
||||||
|
@property (nonatomic, assign) OIMAllowType lookMemberInfo;
|
||||||
|
@property (nonatomic, assign) OIMAllowType applyMemberFriend;
|
||||||
|
@property (nonatomic, assign) NSInteger notificationUpdateTime;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *notificationUserID;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// OIMGroupInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMGroupInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMGroupBaseInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMGroupCreateInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMGroupInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// OIMGroupMemberInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
/// Group Member Information
|
||||||
|
///
|
||||||
|
@interface OIMGroupMemberBaseInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMGroupMemberRole roleLevel;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Group Member Information
|
||||||
|
///
|
||||||
|
@interface OIMGroupMemberInfo : OIMGroupMemberBaseInfo
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *nickname;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *faceURL;
|
||||||
|
/**
|
||||||
|
* Join time
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger joinTime;
|
||||||
|
/**
|
||||||
|
* Method of joining
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) OIMJoinType joinSource;
|
||||||
|
/**
|
||||||
|
* Operator's ID
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *operatorUserID;
|
||||||
|
/**
|
||||||
|
* Mute end timestamp (in seconds)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSTimeInterval muteEndTime;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *inviterUserID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMSetGroupMemberInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *nickname;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *faceURL;
|
||||||
|
@property (nonatomic, assign) OIMGroupMemberRole roleLevel;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// OIMGroupMemberInfo.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMGroupMemberInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMGroupMemberBaseInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMGroupMemberInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMSetGroupMemberInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// OIMLocationElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMLocationElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *desc;
|
||||||
|
@property (nonatomic, assign) double longitude;
|
||||||
|
@property (nonatomic, assign) double latitude;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// OIMLocationElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMLocationElem.h"
|
||||||
|
|
||||||
|
@implementation OIMLocationElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
|
||||||
|
return @{@"desc" : @"description"};
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// OIMMergeElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMMessageElem.h"
|
||||||
|
@class OIMMessageInfo;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMMergeElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *title;
|
||||||
|
@property (nonatomic, nullable, copy) NSArray<NSString *> *abstractList;
|
||||||
|
@property (nonatomic, nullable, copy) NSArray<OIMMessageInfo *> *multiMessage;
|
||||||
|
@property (nonatomic, nullable, copy) NSArray<OIMMessageEntity *> *messageEntityList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// OIMMergeElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMMergeElem.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMMergeElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"multiMessage" : [OIMMessageInfo class],
|
||||||
|
@"messageEntityList" : [OIMMessageEntity class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// OIMMessageElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/7/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMMessageEntity : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *type;
|
||||||
|
@property (nonatomic, assign) NSInteger offset;
|
||||||
|
@property (nonatomic, assign) NSInteger length;
|
||||||
|
@property (nonatomic, copy) NSString *url;
|
||||||
|
@property (nonatomic, copy) NSString *info;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMAdvancedTextElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *text;
|
||||||
|
@property (nonatomic, copy) NSArray <OIMMessageEntity *> *messageEntityList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMMessageElem : NSObject
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMTextElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *content;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMCardElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *userID;
|
||||||
|
@property (nonatomic, copy) NSString *nickname;
|
||||||
|
@property (nonatomic, copy) NSString *faceURL;
|
||||||
|
@property (nonatomic, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMTypingElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *msgTips;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// OIMMessageElem.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/7/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMMessageElem.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
@implementation OIMMessageEntity
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMAdvancedTextElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"messageEntityList" : [OIMMessageEntity class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMMessageElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMTextElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMCardElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMTypingElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,213 @@
|
||||||
|
//
|
||||||
|
// OIMMessageInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMPictureElem.h"
|
||||||
|
#import "OIMSoundElem.h"
|
||||||
|
#import "OIMVideoElem.h"
|
||||||
|
#import "OIMFileElem.h"
|
||||||
|
#import "OIMMergeElem.h"
|
||||||
|
#import "OIMAtElem.h"
|
||||||
|
#import "OIMLocationElem.h"
|
||||||
|
#import "OIMCustomElem.h"
|
||||||
|
#import "OIMQuoteElem.h"
|
||||||
|
#import "OIMNotificationElem.h"
|
||||||
|
#import "OIMFaceElem.h"
|
||||||
|
#import "OIMAttachedInfoElem.h"
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
#import "OIMMessageElem.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMOfflinePushInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *title;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *desc;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *iOSPushSound;
|
||||||
|
@property (nonatomic, assign) BOOL iOSBadgeCount;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *operatorUserID;
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// Message Model
|
||||||
|
///
|
||||||
|
@interface OIMMessageInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *clientMsgID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *serverMsgID;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval createTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval sendTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMConversationType sessionType;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *sendID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *recvID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *handleMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMMessageLevel msgFrom;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMMessageContentType contentType;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMPlatform senderPlatformID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *senderNickname;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *senderFaceUrl;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *content;
|
||||||
|
/**
|
||||||
|
* Message unique sequence number
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger seq;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isRead;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMMessageStatus status;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *attachedInfo;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *localEx;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *ex;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) OIMOfflinePushInfo *offlinePush;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMTextElem *textElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMCardElem *cardElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMPictureElem *pictureElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMSoundElem *soundElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMVideoElem *videoElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMFileElem *fileElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMMergeElem *mergeElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMAtTextElem *atTextElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMLocationElem *locationElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMQuoteElem *quoteElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMCustomElem *customElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMNotificationElem *notificationElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMFaceElem *faceElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMAttachedInfoElem *attachedInfoElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMAdvancedTextElem *advancedTextElem;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMTypingElem *typingElem;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval hasReadTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isReact;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isExternalExtensions;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMReceiptInfo : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User ID - for one-on-one chat
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group ID - for group chat
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *groupID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read message IDs
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSArray<NSString *> *msgIDList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reading time
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger readTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMMessageLevel msgFrom;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMMessageContentType contentType;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMConversationType sessionType;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMMessageRevokedInfo : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the revoker
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSString *revokerID;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *revokerNickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoker's role, e.g., group owner, group administrator
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) OIMGroupMemberRole revokerRole;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *clientMsgID;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval revokeTime;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval sourceMessageSendTime;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *sourceMessageSendID;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *sourceMessageSenderNickname;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMConversationType sessionType;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *ex;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMKeyValue: NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *errMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger errCode;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *typeKey;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *value;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSTimeInterval latestUpdateTime;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMKeyValues: NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *errMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger errCode;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *clientMsgID;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSDictionary<NSString *, OIMKeyValue *> *reactionExtensionList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// OIMMessageInfo.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
@implementation OIMOfflinePushInfo
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
self.title = @"";
|
||||||
|
self.desc = @"";
|
||||||
|
self.ex = @"";
|
||||||
|
self.iOSPushSound = @"";
|
||||||
|
self.iOSBadgeCount = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMMessageInfo
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
self.offlinePush = [OIMOfflinePushInfo new];
|
||||||
|
self.status = OIMMessageStatusUndefine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTimeInterval)hasReadTime {
|
||||||
|
if (_hasReadTime == 0) {
|
||||||
|
_hasReadTime = _attachedInfoElem.hasReadTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _hasReadTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMReceiptInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMMessageRevokedInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMKeyValue
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMKeyValues
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// OIMNotificationElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMGroupMemberInfo.h"
|
||||||
|
#import "OIMGroupInfo.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMNotificationElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *detail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following fields are decoded from the 'detail' field
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong, readonly) OIMGroupMemberInfo *opUser;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong, readonly) OIMGroupMemberInfo *quitUser;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong, readonly) OIMGroupMemberInfo *entrantUser;
|
||||||
|
/**
|
||||||
|
* Information about the new group owner after a group change
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong, readonly) OIMGroupMemberInfo *groupNewOwner;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong, readonly) OIMGroupInfo *group;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong, readonly) NSArray <OIMGroupMemberInfo *> *kickedUserList;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong, readonly) NSArray <OIMGroupMemberInfo *> *invitedUserList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// OIMNotificationElem.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMNotificationElem.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
@implementation OIMNotificationElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
|
||||||
|
return @{@"groupNewOwner" : @"newGroupOwner"};
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray {
|
||||||
|
return @{@"kickedUserList" : [OIMGroupMemberInfo class],
|
||||||
|
@"invitedUserList": [OIMGroupMemberInfo class]
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setDetail:(NSString *)detail {
|
||||||
|
_detail = detail;
|
||||||
|
|
||||||
|
if (detail.length > 0) {
|
||||||
|
OIMNotificationElem *elem = [OIMNotificationElem mj_objectWithKeyValues:detail];
|
||||||
|
_group = elem.group;
|
||||||
|
_opUser = elem.opUser;
|
||||||
|
_quitUser = elem.quitUser;
|
||||||
|
_entrantUser = elem.entrantUser;
|
||||||
|
_kickedUserList = elem.kickedUserList;
|
||||||
|
_invitedUserList = elem.invitedUserList;
|
||||||
|
_groupNewOwner = elem.groupNewOwner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
//
|
||||||
|
// OIMPictureElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
@interface OIMPictureInfo : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique ID, can be left unset
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *uuID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image type, can be left unset
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image size
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image width
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) CGFloat width;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image height
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) CGFloat height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image OSS address
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSString *url;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMPictureElem : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local resource path
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *sourcePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local image details
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong) OIMPictureInfo *sourcePicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Big image details
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong) OIMPictureInfo *bigPicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thumbnail image details
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong) OIMPictureInfo *snapshotPicture;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// OIMPictureElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMPictureElem.h"
|
||||||
|
|
||||||
|
@implementation OIMPictureInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMPictureElem
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// OIMQuoteElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMMessageElem.h"
|
||||||
|
@class OIMMessageInfo;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMQuoteElem : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *text;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, strong) OIMMessageInfo *quoteMessage;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSArray <OIMMessageEntity *> *messageEntityList;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// OIMQuoteElem.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/11.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMQuoteElem.h"
|
||||||
|
|
||||||
|
@implementation OIMQuoteElem
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"messageEntityList" : [OIMMessageEntity class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
//
|
||||||
|
// OIMSearchParam.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
@class OIMMessageInfo;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMSearchParam : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conversation ID, if empty, it's a global search
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSString *conversationID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search keyword list, currently supports only one keyword search
|
||||||
|
*/
|
||||||
|
@property (nonatomic, strong) NSArray *keywordList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keyword match mode, 1 means AND, 2 means OR (currently unused)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger keywordListMatchType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the list of sender user IDs (currently unused)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong) NSArray *senderUserIDList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message type list
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, strong) NSArray *messageTypeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search start time point. Default is 0, meaning search from now. UTC timestamp, unit: seconds
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger searchTimePosition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time range from the start time point, in seconds. Default is 0, meaning no time limit. Provide 24x60x60 to represent the past day.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger searchTimePeriod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current page number, starting from the first page (1). It's invalid when conversationID is empty, i.e., in the global search context.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger pageIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of items per page. It's invalid when conversationID is empty, i.e., in the global search context.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger count;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// For group search
|
||||||
|
@interface OIMSearchGroupParam : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search keywords, currently supports only one keyword (must not be empty)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSArray *keywordList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to search for group IDs based on keywords (note: both cannot be false at the same time). Default is false.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchGroupID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to search for group names based on keywords. Default is false.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchGroupName;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// For friends search
|
||||||
|
///
|
||||||
|
@interface OIMSearchFriendsParam : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search keywords, currently supports only one keyword (must not be empty)
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSArray *keywordList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to search for user IDs based on keywords
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchUserID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to search for nicknames based on keywords. Default is false.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchNickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to search for remarks based on keywords. Default is false.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchRemark;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// For chat history search
|
||||||
|
///
|
||||||
|
@interface OIMGetMessageOptions : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy, nullable) NSString *userID;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *groupID;
|
||||||
|
/**
|
||||||
|
* Conversation ID; if not empty, retrieve messages by conversation ID, otherwise use userID and groupID
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, nullable) NSString *conversationID;
|
||||||
|
/**
|
||||||
|
* Start message clientMsgID
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy, nullable) NSString *startClientMsgID;
|
||||||
|
@property (nonatomic, assign) NSInteger count;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMGetAdvancedHistoryMessageListParam : OIMGetMessageOptions
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMGetHistoryViewType viewType;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMFindMessageListParam : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *conversationID;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSArray <NSString *> *clientMsgIDList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/// For group members search
|
||||||
|
///
|
||||||
|
@interface OIMSearchGroupMembersParam : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *groupID;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSArray *keywordList;
|
||||||
|
/**
|
||||||
|
* Whether to search user IDs based on keywords
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchUserID;
|
||||||
|
/**
|
||||||
|
* Whether to search member nicknames based on keywords. Default is false.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) BOOL isSearchMemberNickname;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger offset;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger count;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// OIMSearchParam.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMSearchParam.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMSearchParam
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
_senderUserIDList = @[];
|
||||||
|
_messageTypeList = @[];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation OIMSearchGroupParam
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMGetMessageOptions
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMGetAdvancedHistoryMessageListParam
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMSearchFriendsParam
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMFindMessageListParam
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMSearchGroupMembersParam
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// OIMSearchResultInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "OIMDefine.h"
|
||||||
|
|
||||||
|
@class OIMMessageInfo;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMSearchResultItemInfo : NSObject
|
||||||
|
/**
|
||||||
|
* Conversation ID
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSString *conversationID;
|
||||||
|
/**
|
||||||
|
* Number of messages in this conversation
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger messageCount;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) OIMConversationType conversationType;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *showName;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *faceURL;
|
||||||
|
/**
|
||||||
|
* List of OIMMessageInfo
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSArray <OIMMessageInfo *> *messageList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMSearchResultInfo : NSObject
|
||||||
|
/**
|
||||||
|
* Total number of messages obtained
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger totalCount;
|
||||||
|
/**
|
||||||
|
* Search results
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSArray <OIMSearchResultItemInfo *> *searchResultItems;
|
||||||
|
/**
|
||||||
|
* Only applicable to the callback result of the findMessageList function
|
||||||
|
*/
|
||||||
|
@property (nonatomic, copy) NSArray <OIMSearchResultItemInfo *> *findResultItems;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface OIMGetAdvancedHistoryMessageListInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) BOOL isEnd;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger lastMinSeq;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger errCode;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *errMsg;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSArray <OIMMessageInfo *> *messageList;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// OIMSearchResultInfo.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMSearchResultInfo.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
#import "OIMMessageInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMSearchResultItemInfo
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"messageList" : [OIMMessageInfo class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMSearchResultInfo
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"searchResultItems" : [OIMSearchResultItemInfo class],
|
||||||
|
@"findResultItems" : [OIMSearchResultItemInfo class]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation OIMGetAdvancedHistoryMessageListInfo
|
||||||
|
|
||||||
|
+ (NSDictionary *)mj_objectClassInArray
|
||||||
|
{
|
||||||
|
return @{@"messageList" : [OIMMessageInfo class]};
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// OIMSimpleRequstInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMSimpleRequstInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *toUserID;
|
||||||
|
/**
|
||||||
|
* Only for adding friend requests
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *reqMsg;
|
||||||
|
/**
|
||||||
|
* Only for setting friend remarks
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *remark;
|
||||||
|
/**
|
||||||
|
* Only for approving a friend request from someone
|
||||||
|
*/
|
||||||
|
@property (nonatomic, nullable, copy) NSString *handleMsg;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// OIMSimpleRequstInfo.m
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "OIMSimpleRequstInfo.h"
|
||||||
|
|
||||||
|
@implementation OIMSimpleRequstInfo
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// OIMSimpleResultInfo.h
|
||||||
|
// OpenIMSDK
|
||||||
|
//
|
||||||
|
// Created by x on 2022/2/14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface OIMSimpleResultInfo : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, copy) NSString *userID;
|
||||||
|
/**
|
||||||
|
* For checkFriend: a result of 1 indicates a friend (and not in the blacklist).
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign) NSInteger result;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue