IMCore接口说明

更新时间:2016/04/29 访问次数:55945

如果是使用OpenIMCore集成,IMSDK为你提供消息通道的能力,即消息发送和消息接收。

你可以基于消息通道的能力,自己完成消息的发送、存储、显示等过程,继而为用户提供IM沟通的能力。

要使用消息通道的基础能力,你只需要关注下面这几个步骤:初始化、登录、发消息、收消息等。

初始化

/**
 *  初始化示例代码
 */
- (BOOL)exampleInit;
{
    /// 设置环境
    [[YWAPI sharedInstance] setEnvironment:YWEnvironmentRelease];
    /// 开启日志
    [[YWAPI sharedInstance] setLogEnabled:YES];
    
    NSLog(@"SDKVersion:%@", [YWAPI sharedInstance].YWSDKIdentifier);
    
    NSError *error = nil;
    
    /// 异步初始化IM SDK
#warning TODO: CHANGE TO YOUR AppKey
    [[YWAPI sharedInstance] syncInitWithOwnAppKey:@"23015524" getError:&error];
    
    if (error.code != 0 && error.code != YWSdkInitErrorCodeAlreadyInited) {
        /// 初始化失败
        return NO;
    } else {
        if (error.code == 0) {
            /// 首次初始化成功
            /// 获取一个IMCore并持有
            self.IMCore = [[YWAPI sharedInstance] fetchNewIMCoreForOpenIM];
        } else {
            /// 已经初始化
        }
        return YES;
    }
}
  • YWAPI的单例是IMSDK的API入口,调用syncInitWithOwnAppKey:getError:方法进行初始化【YWAPI.h】
  • 初始化成功后调用fetchNewIMCoreForOpenIM接口获取并保存YWIMCore的实例,你可以使用YWIMCore的实例建立消息通道。【YWAPI.h】

登录

IMSDK的登录有几个概念:

  • 预登录

    预登录的作用,是为了能在登录成功之前就打开本地数据库,为用户展示本地聊天数据。
    所以一般你可以根据业务的需要,在允许用户查看聊天数据时,就使用调用预登录的接口,如果预登录成功,即可显示本地数据。

  • 真正登录

    无论预登录是否成功,你都需要发起真正登录,才能与IM服务器建立连接,收发IM消息。

建议的登录流程

  • 登录你们App自己的帐号体系,登录成功则下一步
  • 尝试预登录,预登录成功就可以打开会话列表页面,展示本地IM数据
  • 不管预登录是否成功,都需要发起真正登录

请参考:官方demo中callThisAfterISVAccountLoginSuccessWithYWLoginId:passWord:preloginedBlock:successBlock:failedBlock:方法。


登录时机【重要,务必理解下述内容】:

  • 每次App重启后,你都需要手动调用asyncLoginWithCompletionBlock:接口发起登录,IMSDK不会做自动登录。
  • 当你发起登录后,在有结果之前,你都无需再次调用登录,直到aCompletionBlock回调你成功或者失败。
    • 如果登录失败,你可以再次发起登录。
    • 如果登录成功,此次生命周期内,只要没有被踢或者登出,你都无需再次调用发起登录。(前后台切换或者网络切换,IMSDK会自动重连)

预登录

/**
 *  预登陆
 */
- (void)examplePreLoginWithLoginId:(NSString *)loginId successBlock:(void(^)())aPreloginedBlock
{
    /// 预登录
    if ([[self.ywIMKit.IMCore getLoginService] preLoginWithPerson:[[YWPerson alloc] initWithPersonId:loginId]]) {
        /// 预登录成功,直接进入页面,这里可以打开界面
        if (aPreloginedBlock) {
            aPreloginedBlock();
        }
    }
}

真正登录

/**
 *  登录的示例代码
 */
- (void)exampleLoginWithUserID:(NSString *)aUserID password:(NSString *)aPassword successBlock:(void(^)())aSuccessBlock failedBlock:(void (^)(NSError *))aFailedBlock
{
    aSuccessBlock = [aSuccessBlock copy];
    aFailedBlock = [aFailedBlock copy];
    
    /// 登录之前,先告诉IM如何获取登录信息。
    /// 当IM向服务器发起登录请求之前,会调用这个block,来获取用户名和密码信息。
    [[self.ywIMKit.IMCore getLoginService] setFetchLoginInfoBlock:^(YWFetchLoginInfoCompletionBlock aCompletionBlock) {
        aCompletionBlock(YES, aUserID, aPassword, nil, nil);
    }];
    
    /// 发起登录
    [[self.ywIMKit.IMCore getLoginService] asyncLoginWithCompletionBlock:^(NSError *aError, NSDictionary *aResult) {
        if (aError.code == 0 || [[self.ywIMKit.IMCore getLoginService] isCurrentLogined]) {
            /// 登录成功
#ifdef DEBUG
            [[SPUtil sharedInstance] showNotificationInViewController:self.rootWindow.rootViewController title:@"登录成功" subtitle:nil type:SPMessageNotificationTypeSuccess];
#endif
            
            if (aSuccessBlock) {
                aSuccessBlock();
            }
        } else {
            /// 登录失败
            [[SPUtil sharedInstance] showNotificationInViewController:self.rootWindow.rootViewController title:@"登录失败" subtitle:aError.description type:SPMessageNotificationTypeError];
            
            if (aFailedBlock) {
                aFailedBlock(aError);
            }
        }
    }];
}
  • 登录的过程分为两个步骤:
    • 调用setFetchLoginInfoBlock:设置获取登录信息的回调。一般地,你需要在这个回调里先获取该用户的昵称,成功后再调用aCompletionBlock,将userId、password、displayName等信息告知IMSDK。(昵称用于对方收到系统推送时显示)【IYWLoginService.h】
    • 调用asyncLoginWithCompletionBlock:真正发起登录【IYWLoginService.h】

注意: 目前要求登录操作,必须在主线程调用(底层CoreData的NSFetchedResultsController需要在主线程创建才能在主线程回调),否则一些回调比如未读数变更的回调,将会无效。

是否已经登录

你可以通过IYWLoginService.h中的- (BOOL)hasLoginThread函数判断是否已经发起登录。

发消息

- (void)sendImageMessageData:(NSData *)imageData
{
	/// 构造消息体
	YWMessageBodyImage *imageMessageBody = [[YWMessageBodyImage alloc] initWithMessageImageData:imageData];
    
	/// 获取会话
	YWP2PConversation *conv = [YWP2PConversation fetchConversationByPerson:[[YWPerson alloc] initWithPersonId:@"uid1"] creatIfNotExist:YES baseContext:self.IMCore];

	///	发送消息 
	[conv asyncSendMessageBody:imageMessageBody controlParameters:nil progress:^(CGFloat progress, NSString *messageID) {

		/// 更新消息进度显示
		 
	} completion:^(NSError *error, NSString *messageID) {
		if (error) {
			/// 消息发送失败,提示用户
		}
	}];
}
  • 消息发送分为以下几个步骤:
    • 构造消息体:根据你要发送的消息类型,构造YWMessageBody的子类对象,塞入要发送的数据。【YWMessageBody.h】
    • 构造消息控制参数(用于控制消息Push文案、是否仅存本地等),详细请阅读本文后面的章节消息发送控制
    • 获取会话:根据接收方,获取对应的会话,例如一个单聊会话。
    • 发送消息:通过YWConversation的asyncSendMessageBody:progress:completion:方法发送消息。

收消息

[[self.IMCore getConversationService] addOnNewMessageBlockV2:^(NSArray *aMessages, BOOL aIsOffline) {
    [aMessages enumerateObjectsUsingBlock:^(id  obj, NSUInteger idx, BOOL * stop) {
        id<IYWMessage> message = [obj conformsToProtocol:@protocol(IYWMessage)] ? obj : nil;
        if (message) {
            /// 处理消息
        }
    }];
} forKey:self.description ofPriority:YWBlockPriorityDeveloper];
  • 你需要在获取到YWIMCore实例之后,就添加新消息的监听
  • aMessages数组中的每一个对象都是遵循IYWMessage协议的对象,你可以从中获取到消息的具体信息。

账号设置

目前账号设置支持单聊、群聊的消息接收设置和开发者自定义设置,方法声明在YWIMCore层中的IYWSettingService中,这个头文件中的方法分为同步方法和异步方法,同步方法只获取本地的数据,异步方法则需要发送网络请求。

同步服务端设置

开发者可以通过

/**
 *  将本地的消息接收设置更新至服务端的状态,sdk内部每24h同步一次,开发者可以视自己需求调用
 */
- (void)syncMessageSettingFromServerWithompletionBlcok:(YWCompletionBlock)aCompletion;

来同步服务端的设置,同步成功后开发者可以在aCompletion中通过调用同步方法来获取本地的数据。

单聊消息的设置

单聊消息可以设置在后台时消息是否PUSH,屏蔽单聊消息则是通过更多功能中的黑名单来实现的。

/// 获取person 发送的消息后台是否push
- (BOOL)getMessagePushEnableForPerson:(YWPerson *)person;

/// 异步设置person 发送的消息后台是否push
- (void)asyncSetMessagePushEnable:(BOOL)enable ForPerson:(YWPerson *)person completion:(YWCompletionBlock)aCompletion;

群聊消息的设置

群聊消息可以分别设置群普通消息的接收和群@消息的接收方式,需要注意的是,群普通消息分为接收并PUSH、接收不PUSH和不接收三种,而群@消息只有接收并PUSH和不接收两种,其取值参考IYWSettingServiceDef中的YWMessageFlagYWAtMessageFlag两个枚举:

typedef NS_ENUM(NSInteger, YWMessageFlag) {
    YWMessageFlagNotReceive,            // 屏蔽消息
    YWMessageFlagReceiveButNoAlert,     // 前台在线时接收消息,后台不push
    YWMessageFlagReceive,               // 正常接收消息,后台有push
};

typedef NS_ENUM(NSInteger, YWAtMessageFlag) {
    YWAtMessageFlagNotReceive,            // 屏蔽消息
    YWAtMessageFlagReceive,               // 正常接收消息,后台有push
};

群消息设置的方法较多,开发者可以移步IYWSettingService头文件中查看。

自定义设置

云旺提供了开发者保存自定义设置的功能,客户端和服务器均为透传,当开发者需要多端同步自定义设置时,可以通过

/**
 *  获取开发者自定义的设置项
 */
- (NSDictionary *)getExtraSettings;

/**
 *  异步设置自定义设置项,服务端只负责保存,不会进行解析
 */
- (void)asyncSetExtraSettings:(NSDictionary *)settings completion:(YWCompletionBlock)aCompletion;

来获取和设置。

消息发送控制

IMSDK提供了消息发送控制的能力,你利用YWConversation.h中消息发送接口携带的controlParameters参数,控制对方iOS设备接收消息的推送文案、推送声音、是否需要推送等,也可以控制消息仅存本地而不发送到对方。

控制对方iOS设备的推送

如下面的代码所示,通过controlParameters参数,控制了对方收到推送的推送文案,你还可以控制是否弹出Push、Push的声音等等,详见:YWConversationServiceDef.h

/**
 *  发送透传指令
 *  并且展示了如何在客户端控制对方iOS设备收到的Push文案
 *  不显示在会话列表和聊天页面,开发者可以监听到该消息,做特定的逻辑处理
 */
- (void)exampleSendTransparentCommand:(NSString *)aCommand inConversation:(YWConversation *)aConversation completion:(YWMessageSendingCompletionBlock)aCompletion
{
    YWMessageBodyCustomize *body = [[YWMessageBodyCustomize alloc] initWithMessageCustomizeContent:aCommand summary:@"阅后即焚" isTransparent:YES];
    /// 控制对方收到的Push文案,你还可以控制推送声音,是否需要push等,详见:YWConversationServiceDef.h
    NSDictionary *controlParameters = @{kYWMsgCtrlKeyPush:@{kYWMsgCtrlKeyPushKeyHowToPush:@{kYWMsgCtrlKeyPushKeyHowToPushKeyTitle:@"请务必阅后即焚"}}};
    [aConversation asyncSendMessageBody:body controlParameters:controlParameters progress:NULL completion:aCompletion];
}
/**消息控制字段定义**/
/**
 **示例**
 
 @{
     kYWMsgCtrlKeyPush:@{
         kYWMsgCtrlKeyPushKeyNeedPush:@(1),
         kYWMsgCtrlKeyPushKeyHowToPush:@{
             kYWMsgCtrlKeyPushKeyHowToPushKeyTitle:@"推送文案自定义",
             kYWMsgCtrlKeyPushKeyHowToPushKeySound:@"customsound.caf",
             kYWMsgCtrlKeyPushKeyHowToPushKeyData:@"推送透传数据",
         },
     },
     kYWMsgCtrlKeyClientLocal:@{kYWMsgCtrlKeyClientLocalKeyOnlySave:@(YES)}, /// 本地保存
 }
 
 *******
 */

/// 推送控制
/// 值一个字典,控制推送。该字典包含:kYWMsgCtrlKeyPushKeyNeedPush、kYWMsgCtrlKeyPushKeyHowToPush
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyPush;
/// 值为一个整数,控制是否推送:没有这个key为需要推送,@(1)为需要推送,@(0)为不需要推送
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyPushKeyNeedPush;
/// 值为一个字典,控制推送样式。该字典包含:kYWMsgCtrlKeyPushKeyHowToPushKeyTitle、kYWMsgCtrlKeyPushKeyHowToPushKeySound、kYWMsgCtrlKeyPushKeyHowToPushKeyData
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyPushKeyHowToPush;
/// 值为字符串,控制推送文案
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyPushKeyHowToPushKeyTitle;
/// 值为字符串,控制推送声音文件
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyPushKeyHowToPushKeySound;
/// 值为字符串,控制推送携带的数据
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyPushKeyHowToPushKeyData;

/// 值为一个字典,控制客户端本地行为。该字典包含:kYWMsgCtrlKeyClientLocalKeyOnlySave
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyClientLocal;
/// 值为一个bool值,控制该消息仅保存本地,不发送到服务器。无此key或者@(0)则为需要发送,@(1)则为仅保存本地
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyClientLocalKeyOnlySave;
/// 值为一个bool值,控制该消息保存本地时即标记删除,但仍然发送到服务器,本地因为被标记删除所以不会显示。无此key或者@(0)则为不标记删除,@(1)则为标记删除
FOUNDATION_EXTERN NSString *const kYWMsgCtrlKeyClientLocalKeyMarkDeleted;

控制消息仅存本地不发送到对方

下面的代码展示了使用controlParameters字段控制消息不发送给对方,只在本地展示

/**
 *  插入本地消息
 *  消息不会被发送到对方,仅本地展示
 */
- (void)exampleInsertLocalMessageBody:(YWMessageBody *)aBody inConversation:(YWConversation *)aConversation
{
    NSDictionary *controlParameters = @{kYWMsgCtrlKeyClientLocal:@{kYWMsgCtrlKeyClientLocalKeyOnlySave:@(YES)}}; /// 控制字段
    [aConversation asyncSendMessageBody:aBody controlParameters:controlParameters progress:NULL completion:NULL];
}

控制消息发送到对方,但本地不显示

  • 在消息发送接口的controlParameters字典中添加kYWMsgCtrlKeyClientLocalKeyMarkDeleted,并设置为@(YES)
  • 该字段表示,消息会被发送给对方,但是本地不会显示出来
  • 一般用于用户进入客服聊天界面时,主动发送一条消息让客服知道,但用户并无感知

示例如下:

YWConversationViewController *controller = [YWConversationViewController makeControllerWithIMKit:self.imkit conversation:conversation];
    __weak typeof(controller) weakController = controller;
    __weak typeof(self) weakSelf = self;
    
    [controller setViewDidLoadBlock:^{
        BOOL needToSayHi = ...; /// 根据你的需要,确定是否需要自动打招呼。一般需要判断,对方是否客服以及最近一天是否已经和客服打过招呼
        NSString *hiContent = @"Hello"; /// 根据你的需要设置合适的招呼内容
        if (needToSayHi) {
            [weakController.conversation asyncSendMessageBody:[[YWMessageBodyText alloc] initWithMessageText:hiContent] controlParameters:@{kYWMsgCtrlKeyClientLocal:@{kYWMsgCtrlKeyClientLocalKeyMarkDeleted:@(YES)}} progress:NULL completion:NULL];
        }
    }];

发送消息透传指令

消息透传指令用于在当前客户端发送一条消息给对方,对方收到后,不会在聊天页面或者会话页面有任何展示。你可以根据需要,监听该消息,并处理相关逻辑。

下面的代码用透传指令演示了阅后即焚的功能,对方收到消息后,展示一个弹框。(你也可以不做任何提示,仅做逻辑处理)。

发送透传消息

/**
 *  发送透传指令
 *  并且展示了如何在客户端控制对方iOS设备收到的Push文案
 *  不显示在会话列表和聊天页面,开发者可以监听到该消息,做特定的逻辑处理
 */
- (void)exampleSendTransparentCommand:(NSString *)aCommand inConversation:(YWConversation *)aConversation completion:(YWMessageSendingCompletionBlock)aCompletion
{
    YWMessageBodyCustomize *body = [[YWMessageBodyCustomize alloc] initWithMessageCustomizeContent:aCommand summary:@"阅后即焚" isTransparent:YES];
    /// 控制对方收到的Push文案,你还可以控制推送声音,是否需要push等,详见:YWConversationServiceDef.h
    NSDictionary *controlParameters = @{kYWMsgCtrlKeyPush:@{kYWMsgCtrlKeyPushKeyNeedPush:@(0)}};
    [aConversation asyncSendMessageBody:body controlParameters:controlParameters progress:NULL completion:aCompletion];
}

监听透传消息

你需要监听所有消息,并可以对透传消息做特定的处理。下面的代码监听了所有消息,当消息体是透传指令时,展示一个弹框。

/**
 *  监听新消息
 */
- (void)exampleListenNewMessage
{
    [[self.ywIMKit.IMCore getConversationService] addOnNewMessageBlockV2:^(NSArray *aMessages, BOOL aIsOffline) {
        /// 你可以在此处根据需要播放提示音
        
        /// 展示透传消息
        [aMessages enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            id<IYWMessage> msg = obj;
            YWMessageBodyCustomize *body = nil;
            if ([msg respondsToSelector:@selector(messageBody)]) {
                body = [[msg messageBody] isKindOfClass:[YWMessageBodyCustomize class]] ? (YWMessageBodyCustomize *)[msg messageBody] : nil;
            }
            if (body) {
                NSData *contentData = [body.content dataUsingEncoding:NSUTF8StringEncoding];
                NSDictionary *contentDictionary = [NSJSONSerialization JSONObjectWithData:contentData
                                                                                  options:0
                                                                                    error:NULL];

                NSString *messageType = contentDictionary[@"customizeMessageType"];
                if ([messageType isEqualToString:@"yuehoujifen"] && body.isTransparent) {
                    NSString *text = contentDictionary[@"Text"];
                    if (text.length > 0) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"阅后即焚" message:text delegate:nil cancelButtonTitle:@"朕知道了" otherButtonTitles:nil];
                            [av show];
                        });
                    }
                }
            }
        }];
    } forKey:self.description ofPriority:YWBlockPriorityDeveloper];
}

消息生命周期回调

对于每一条发出的消息,IMSDK均会给予回调,通过如下的代码添加监听,你需要实现YWMessageLifeDelegate协议:

/**
 *  监听自己发送的消息的生命周期
 */
- (void)exampleListenMyMessageLife
{
    [[self.ywIMKit.IMCore getConversationService] addMessageLifeDelegate:self forPriority:YWBlockPriorityDeveloper];
}

消息发送前

你可以通过消息发送前的回调,进行修改消息内容、修改会话或者干脆控制不发出该消息。(影响所有消息,请务必谨慎调试)。

下面的代码展示了,所发送的消息包含违禁词语时,改为插入一条本地消息。
controlParameters的定义与前面消息发送控制中的controlParameters一致。

/// 当你监听了消息生命周期,IMSDK会回调以下两个函数
- (YWMessageLifeContext *)messageLifeWillSend:(YWMessageLifeContext *)aContext
{
    /// 你可以通过返回context,来实现改变消息的能力
    if ([aContext.messageBody isKindOfClass:[YWMessageBodyText class]]) {
        NSString *text = [(YWMessageBodyText *)aContext.messageBody messageText];
        if ([text rangeOfString:@"法轮功"].location != NSNotFound) {
            YWMessageBodySystemNotify *bodyNotify = [[YWMessageBodySystemNotify alloc] initWithContent:@"消息包含违禁词语"];
            [aContext setMessageBody:bodyNotify];
            
            NSDictionary *params = @{kYWMsgCtrlKeyClientLocal:@{kYWMsgCtrlKeyClientLocalKeyOnlySave:@(YES)}};
            [aContext setControlParameters:params];
            
            return aContext;
        }
    }
    
    return nil;
}

消息发送后

- (void)messageLifeDidSend:(NSString *)aMessageId conversationId:(NSString *)aConversationId result:(NSError *)aResult
{
    /// 你可以在消息发送完成后,做一些事情,例如播放一个提示音等等
}

FAQ

ios 推送的消息体只显示 “body”

返回
顶部