IM 登录最佳实践
更新时间: 2024/03/14 17:08:38
登录对于 IM 产品来说至关重要,是后续业务顺利进行的前提条件。开发者集成 NIM SDK 的各项能力时,如果未能正确使用登录接口或处理登录状态,将引发不必要的问题,影响开发进度。本文介绍如何以最佳姿势进行手动登录和自动登录,进而实现 IM 登录。
- 手动登录:首次登录 IM 时调用
NIMLoginManager.login:token:completion:
方法实现。 - 自动登录:手动登录 IM 成功之后调用
autoLogin:token:
。调用时机为:手动登陆成功之后下次启动应用时;自动登录之后的应用存活期间,因为网络断开 SDK 会自己重连,不需要业务层调用。
本文的手动登录仅以静态 Token 登录为例,更多登录相关说明请参见登录 IM。
前提条件
-
已在云信控制台创建应用,获取 App Key。
-
已通过云信服务端注册 IM 账号 ,获取 IM 账号(
accid
)和对应的静态token
。您也可通过控制台注册 IM 测试账号。测试账号及对应的
token
仅适用于调试环境,线上生产环境必须将测试账号及其token
替换为云信服务端生成的正式accid
和token
。
实现方案
手动登录
IM 手动登录接口的调用,对应用户手动输入账号和密码进行登录的场景。一般情况下,该接口需在应用的didFinishLaunchingWithOptions
启动后,用户在登录界面点击登录时调用。其他情况一般不需要调用手动登录接口,除非是账号被踢下线、切换账号、注销登录后重新登录等情况。在登录界面中,IM 登录可以作为整个应用登录过程的一个环节。常见的方案是先实现应用自身账号体系的登录,成功后再使用返回的accid
和token
进行 IM 的登录。
-
手动登录流程
-
接口调用
-
调用
login:token:completion:
方法手动登录云信IM。可以在调用手动登录接口时,在登录界面加上等待加载框,等收到登录结果之后再隐藏该等待加载框。登录没有返回 error 就是登录成功。
-
调用后处理。
- 如果登录成功,保存 IM 的
accid
和token
到本地,方便下次应用启动自动登录时使用。 - 如果登录失败,清理本地保存的用户登录信息,防止下次启动走自动登录逻辑。
- 如果登录成功,保存 IM 的
示例代码如下:
[[[NIMSDK sharedSDK] loginManager] login:accid token:token completion:^(NSError * _Nullable error) { if (error) { } else { [[NSUserDefaults standardUserDefaults] setObject:accid forKey:@"NIMAccid"]; [[NSUserDefaults standardUserDefaults] setObject:token forKey:@"NIMToken"]; FirstViewController *mainTab = [[FirstViewController alloc] init]; [UIApplication sharedApplication].delegate.window.rootViewController = mainTab; } }];
-
自动登录
手动登录 IM 成功后,下次启动应用可以使用云信 IM 的自动登录模式。自动登录后,即使登录未完成或者网络无法访问,应用也可以直接访问用户本地 SDK 数据。
自动登录主要针对应用被清理掉后,再次点击图标启动时,无需输入用户名和密码即可完成登录的场景。自动登录还有一个作用,即在网络不佳且账号和密码本身正常(未被封禁,且账号密码均正确)时,如果启动应用时调用手动登录接口未成功,SDK 会自动进行重连登录,不需要上层开发者去做额外的重登逻辑。
-
自动登录流程
-
接口调用
调用
autoLogin:token:
或autoLogin:
方法进行自动登录。一般在应用启动和初始化 SDK 之后,如果判断本地已经有持久化的账号和密码即可进行自动登录,自动登录没有回调结果,在跳转到应用首页之前调用一次即可。自动登录的使用限制如下:
- 自动登录只能登录上次登录的IM 账号,不能登录其他账号。
- 需要某个 IM 账号曾经通过手动登录接口登录成功后才可以调用。
- 无论之前是否曾经手动登录成功,只要最近一次手动登录接口调用失败,则不可以继续自动登录。
- 在被云信服务端踢下线、被同时在线的其他端踢下线、被封禁账号、登录密码错误等情况下,后续自动登录将无效,需要用户通过手动登录接口重新登录。更多相关说明,见下文的登录状态处理。
实现自动登录的示例代码如下(仅以
autoLogin:token:
的调用为例):[[NIMSDK sharedSDK].loginManager addDelegate:self]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; if ([[userDefaults objectForKey:@"NIMToken"] length] > 0) { //自动登录 [[NIMSDK sharedSDK].loginManager autoLogin:[userDefaults objectForKey:@"NIMAccid"] token:[userDefaults objectForKey:@"NIMToken"]]; FirstViewController *firstVc = [[FirstViewController alloc] init]; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:firstVc]; firstVc.title = @"第一个页面"; self.window.rootViewController = nav; } else { //登录 LoginViewController *loginVc = [[LoginViewController alloc] init]; UINavigationController *loginNav = [[UINavigationController alloc] initWithRootViewController:loginVc]; loginVc.title = @"登录"; self.window.rootViewController = loginNav; }
登录状态处理
IM 登录状态表示当前登录的 NIM SDK 实例与云信服务端的长连接状态,也可以理解为用户设备和云信服务端的网络连接状态。
初始化 SDK 之后,可调用NIMLoginManager.addDelegate
方法注册onLogin:
登录回调、onKickout:
被踢回调和onAutoLoginFailed:
自动登录失败回调,监听当前的登录状态,并通过 UI 层提示用户。其他使用场景一般只需要在手动登录成功后或者自动登录期间才需要处理 IM 登录状态。
登录的状态监听建议放在您应用的AppDelegate
里。
登录状态处理的流程图如下:
示例代码如下:
@interface AppDelegate ()<NIMLoginManagerDelegate>
@end
[[NIMSDK sharedSDK].loginManager addDelegate:self];
#pragma mark - 登录状态监听
- (void)onLogin:(NIMLoginStep)step {
switch (step) {
case NIMLoginStepLinking: {
NSLog(@"---# 连接服务器ing");
break;
}
case NIMLoginStepLinkOK: {
NSLog(@"---# 连接服务器成功");
break;
}
case NIMLoginStepLinkFailed: {
NSLog(@"---# 连接服务器失败");
break;
}
case NIMLoginStepLogining: {
NSLog(@"---# 登录ing");
break;
}
case NIMLoginStepLoginOK: {
NSLog(@"---# 登录成功");
break;
}
case NIMLoginStepLoginFailed: {
NSLog(@"---# 登录失败");
break;
}
case NIMLoginStepSyncing: {
NSLog(@"---# 开始同步数据");
break;
}
case NIMLoginStepSyncOK: {
NSLog(@"---# 同步数据完成");
break;
}
case NIMLoginStepLoseConnection: {
NSLog(@"---# 连接断开");
break;
}
case NIMLoginStepNetChanged: {
NSLog(@"---# 网络切换");
break;
}
case NIMLoginStepLogout: {
NSLog(@"---# 登出");
break;
}
}
}
@interface AppDelegate ()<NIMLoginManagerDelegate>
@end
[[NIMSDK sharedSDK].loginManager addDelegate:self];
#pragma mark - 被踢(服务器/其他端)回调
- (void)onKickout:(NIMLoginKickoutResult *)result {
//被踢的回调,有被踢的原因,需要在这里logout。
[[NIMSDK sharedSDK].loginManager logout:^(NSError * _Nullable error) {
//这里跳回登录页面
self.window.rootViewController = [LoginViewController new];
[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"NIMAccid"];
[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"NIMToken"];
}];
}
@interface AppDelegate ()<NIMLoginManagerDelegate>
@end
[[NIMSDK sharedSDK].loginManager addDelegate:self];
#pragma mark - 自动登录失败
- (void)onAutoLoginFailed:(NSError *)error {
//这里跳转到登录页面重新登录
if (error) {
self.window.rootViewController = [LoginViewController new];
}
}