- 充值页面
- 充值页面返回挽留弹窗 - 圈子一级页面接口数据接入 - 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
|
||||
pod 'GYSDK' #个推一键登录
|
||||
|
||||
pod 'OpenIMSDK' #OpenIM
|
||||
|
||||
#高德地图
|
||||
pod 'AMap3DMap' #3D地图SDK
|
||||
pod 'AMapSearch' #地图SDK搜索功能
|
||||
|
|
|
|||
41
Podfile.lock
41
Podfile.lock
|
|
@ -82,12 +82,44 @@ PODS:
|
|||
- MarqueeLabel (4.5.3)
|
||||
- Masonry (1.1.0)
|
||||
- MBProgressHUD (1.2.0)
|
||||
- MJExtension (3.4.2)
|
||||
- MJRefresh (3.7.9)
|
||||
- Moya (15.0.0):
|
||||
- Moya/Core (= 15.0.0)
|
||||
- Moya/Core (15.0.0):
|
||||
- Alamofire (~> 5.0)
|
||||
- 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)
|
||||
- RxCocoa (6.8.0):
|
||||
- RxRelay (= 6.8.0)
|
||||
|
|
@ -138,6 +170,7 @@ DEPENDENCIES:
|
|||
- MJRefresh
|
||||
- Moya
|
||||
- ObjectMapper
|
||||
- OpenIMSDK
|
||||
- Popover
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
|
|
@ -179,9 +212,12 @@ SPEC REPOS:
|
|||
- lottie-ios
|
||||
- MarqueeLabel
|
||||
- Masonry
|
||||
- MJExtension
|
||||
- MJRefresh
|
||||
- Moya
|
||||
- ObjectMapper
|
||||
- OpenIMSDK
|
||||
- OpenIMSDKCore
|
||||
- Popover
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
|
|
@ -235,9 +271,12 @@ SPEC CHECKSUMS:
|
|||
MarqueeLabel: 0c57d4c6634e04a6d015af79f7c9a175b2309525
|
||||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||
MBProgressHUD: 1b0fb447e80a0fda94808180750e8b78a07b3cd2
|
||||
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
||||
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
|
||||
OpenIMSDK: c1880296ead605bcac2a289ad0aef9170fe6e6df
|
||||
OpenIMSDKCore: 75caba22be8ee484011f367711178312bd64a17d
|
||||
Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
|
||||
RxCocoa: 2d33c1e1e5d66492052ad46b11024ae287572880
|
||||
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
||||
|
|
@ -256,6 +295,6 @@ SPEC CHECKSUMS:
|
|||
URLNavigator: e9c0426ba6e6ac57f34d018bbf3df840797f984d
|
||||
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
|
||||
|
||||
PODFILE CHECKSUM: 7d3667576e8d6c3f1a98be0e406f215041cf2eb7
|
||||
PODFILE CHECKSUM: d9389fd0d3da8895e9ddac8adbec655edaf9bb3d
|
||||
|
||||
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)
|
||||
- Masonry (1.1.0)
|
||||
- MBProgressHUD (1.2.0)
|
||||
- MJExtension (3.4.2)
|
||||
- MJRefresh (3.7.9)
|
||||
- Moya (15.0.0):
|
||||
- Moya/Core (= 15.0.0)
|
||||
- Moya/Core (15.0.0):
|
||||
- Alamofire (~> 5.0)
|
||||
- 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)
|
||||
- RxCocoa (6.8.0):
|
||||
- RxRelay (= 6.8.0)
|
||||
|
|
@ -138,6 +170,7 @@ DEPENDENCIES:
|
|||
- MJRefresh
|
||||
- Moya
|
||||
- ObjectMapper
|
||||
- OpenIMSDK
|
||||
- Popover
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
|
|
@ -179,9 +212,12 @@ SPEC REPOS:
|
|||
- lottie-ios
|
||||
- MarqueeLabel
|
||||
- Masonry
|
||||
- MJExtension
|
||||
- MJRefresh
|
||||
- Moya
|
||||
- ObjectMapper
|
||||
- OpenIMSDK
|
||||
- OpenIMSDKCore
|
||||
- Popover
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
|
|
@ -235,9 +271,12 @@ SPEC CHECKSUMS:
|
|||
MarqueeLabel: 0c57d4c6634e04a6d015af79f7c9a175b2309525
|
||||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||
MBProgressHUD: 1b0fb447e80a0fda94808180750e8b78a07b3cd2
|
||||
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
|
||||
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
|
||||
OpenIMSDK: c1880296ead605bcac2a289ad0aef9170fe6e6df
|
||||
OpenIMSDKCore: 75caba22be8ee484011f367711178312bd64a17d
|
||||
Popover: 10e1d9528f81d9504df984b7b3f491292bc1822d
|
||||
RxCocoa: 2d33c1e1e5d66492052ad46b11024ae287572880
|
||||
RxDataSources: aa47cc1ed6c500fa0dfecac5c979b723542d79cf
|
||||
|
|
@ -256,6 +295,6 @@ SPEC CHECKSUMS:
|
|||
URLNavigator: e9c0426ba6e6ac57f34d018bbf3df840797f984d
|
||||
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
|
||||
|
||||
PODFILE CHECKSUM: 7d3667576e8d6c3f1a98be0e406f215041cf2eb7
|
||||
PODFILE CHECKSUM: d9389fd0d3da8895e9ddac8adbec655edaf9bb3d
|
||||
|
||||
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