本文已 ReactNative 集成 NIM_iOS_Demo_v4.2.0 为例。Xcode版本为9.0
本人是在已有的ReactNative(以下简称RN)工程下集成云信IM(其他各版本集成方式大同小异)
1. 使用 cocoapods 来安装网易云信依赖
1.首先在 terminal 里进入到自己RN项目ios目录下, 运行 pod init ,(如果电脑没安装cocoapods的,请先安装 cocoapods ),运行完成后,会在当前所在目录下生成 Podfile 文件。
2. 在 Podfile 里添加网易云信的依赖
-
terminal 进入到 RN ios目录下执行 pod init,执行后在 ios 目录下生成 Podfile 文件。
-
在下载好的云信demo里 NIMDemo 目录下找到 Podfile 文件,复制文件里面的内容到自己的 Podfile 文件里。此部完成后的结果如下
source \'https://github.com/CocoaPods/Specs.git\'
platform :ios, \'9.0\'
# Mall为 RN 工程名字
workspace \'Mall.xcworkspace\'
target \'Mall\' do
pod \'yoga\', :path => \'../node_modules/react-native/ReactCommon/yoga\'
pod \'React\', :path => \'../node_modules/react-native\'
pod \'SDWebImage\', \'4.0.0\'
pod \'Toast\', \'~> 3.1.0\'
pod \'M80AttributedLabel\', \'~> 1.6.3\'
pod \'TZImagePickerController\', \'~> 1.9.0\'
pod \'FMDB\', \'~> 2.7.2\'
pod \'Reachability\', \'~> 3.2\'
pod \'CocoaLumberjack\', \'~> 3.2.1\'
pod \'SSZipArchive\', \'~> 1.8.1\'
pod \'SVProgressHUD\', \'~> 2.0.3\'
# 网易云信的 NIMKit 包
pod \'NIMKit/Full\', \'~> 1.9.1\'
end
此处和源码里的podfile内容有点不一致,如果不太清楚各项配置的意思,按照我的配置来就行了。
- 添加完成后在 terminal 窗口里(Podfile 目录中)执行
pod install,执行完成后会在ios目录下生成对应的Mall.xcworkspace文件,以后使用Xcode打开项目就是双击此文件即可。
3. 拷贝IM源码到RN里
- 将demo中的 NIMDemo 目录下的 Classes 和 Supporting Files 拷贝到项目的 ios/Mall 目录下 (与Images.xcassets文件夹同级)

拷贝文件
-
将 Supporting Files 目录下的
Info.plistnim_debug.xcconfignim_release.xcconfig和main.m文件删除 -
将
NTESAppDelegate.m内容和自己工程中的AppDelegate.m文件中的代码进行合并,并修改和去掉部分不需要的代码。
如下代码是我的AppDelegate.m文件的内容
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "NTESLoginViewController.h"
#import "UIView+Toast.h"
#import "NTESService.h"
#import "NTESNotificationCenter.h"
#import "NTESLogManager.h"
#import "NTESDemoConfig.h"
#import "NTESSessionUtil.h"
#import "NTESMainTabController.h"
#import "NTESLoginManager.h"
#import "NTESCustomAttachmentDecoder.h"
#import "NTESClientUtil.h"
#import "NTESNotificationCenter.h"
#import "NIMKit.h"
#import "NTESSDKConfigDelegate.h"
#import "NTESCellLayoutConfig.h"
#import "NTESSubscribeManager.h"
#import "NTESRedPacketManager.h"
#import "NTESBundleSetting.h"
@import PushKit;
NSString *NTESNotificationLogout = @"NTESNotificationLogout";
@interface AppDelegate ()<NIMLoginManagerDelegate,PKPushRegistryDelegate>
@property (nonatomic,strong) NTESSDKConfigDelegate *sdkConfigDelegate;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"Mall"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[self initYunXin];
return YES;
}
- (void)initYunXin
{
[self setupNIMSDK];
[self setupServices];
[self registerPushService];
[self commonInitListenEvents];
// 因为本项目想实现的功能是启动进入的是 RN 界面,在需要的时候,从 RN 页面跳转到原生 iOS 界面
//self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//self.window.backgroundColor = [UIColor grayColor];
//[self.window makeKeyAndVisible];
//[application setStatusBarStyle:UIStatusBarStyleLightContent];
//[self setupMainViewController];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[[NIMSDK sharedSDK] loginManager] removeDelegate:self];
}
#pragma mark - ApplicationDelegate
- (void)applicationWillResignActive:(UIApplication *)application {
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSInteger count = [[[NIMSDK sharedSDK] conversationManager] allUnreadCount];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
}
- (void)applicationWillTerminate:(UIApplication *)application {
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[[NIMSDK sharedSDK] updateApnsToken:deviceToken];
DDLogInfo(@"didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
DDLogInfo(@"receive remote notification: %@", userInfo);
}
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
DDLogError(@"fail to get apns token :%@",error);
}
#pragma mark PKPushRegistryDelegate
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type
{
if ([type isEqualToString:PKPushTypeVoIP])
{
[[NIMSDK sharedSDK] updatePushKitToken:credentials.token];
}
}
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
{
DDLogInfo(@"receive payload %@ type %@",payload.dictionaryPayload,type);
NSNumber *badge = payload.dictionaryPayload[@"aps"][@"badge"];
if ([badge isKindOfClass:[NSNumber class]])
{
[UIApplication sharedApplication].applicationIconBadgeNumber = [badge integerValue];
}
}
- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(NSString *)type
{
DDLogInfo(@"registry %@ invalidate %@",registry,type);
}
#pragma mark - openURL
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[[NTESRedPacketManager sharedManager] application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
return YES;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
[[NTESRedPacketManager sharedManager] application:app openURL:url options:options];
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
//目前只有红包跳转
return [[NTESRedPacketManager sharedManager] application:application handleOpenURL:url];
}
#pragma mark - misc
- (void)registerPushService
{
//apns
[[UIApplication sharedApplication] registerForRemoteNotifications];
UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
//pushkit
PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}
//- (void)setupMainViewController
//{
// LoginData *data = [[NTESLoginManager sharedManager] currentLoginData];
// NSString *account = [data account];
// NSString *token = [data token];
//
// //如果有缓存用户名密码推荐使用自动登录
// if ([account length] && [token length])
// {
// NIMAutoLoginData *loginData = [[NIMAutoLoginData alloc] init];
// loginData.account = account;
// loginData.token = token;
//
// [[[NIMSDK sharedSDK] loginManager] autoLogin:loginData];
// [[NTESServiceManager sharedManager] start];
// NTESMainTabController *mainTab = [[NTESMainTabController alloc] initWithNibName:nil bundle:nil];
// self.window.rootViewController = mainTab;
// }
// else
// {
// [self setupLoginViewController];
// }
//}
- (void)commonInitListenEvents
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(logout:)
name:NTESNotificationLogout
object:nil];
[[[NIMSDK sharedSDK] loginManager] addDelegate:self];
}
//- (void)setupLoginViewController
//{
// [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
// NTESLoginViewController *loginController = [[NTESLoginViewController alloc] init];
// UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:loginController];
// self.window.rootViewController = nav;
//}
#pragma mark - 注销
-(void)logout:(NSNotification *)note
{
[self doLogout];
}
- (void)doLogout
{
[[NTESLoginManager sharedManager] setCurrentLoginData:nil];
[[NTESServiceManager sharedManager] destory];
// [self setupLoginViewController];
}
#pragma NIMLoginManagerDelegate
-(void)onKick:(NIMKickReason)code clientType:(NIMLoginClientType)clientType
{
NSString *reason = @"你被踢下线";
switch (code) {
case NIMKickReasonByClient:
case NIMKickReasonByClientManually:{
NSString *clientName = [NTESClientUtil clientName:clientType];
reason = clientName.length ? [NSString stringWithFormat:@"你的帐号被%@端踢出下线,请注意帐号信息安全",clientName] : @"你的帐号被踢出下线,请注意帐号信息安全";
break;
}
case NIMKickReasonByServer:
reason = @"你被服务器踢下线";
break;
default:
break;
}
[[[NIMSDK sharedSDK] loginManager] logout:^(NSError *error) {
[[NSNotificationCenter defaultCenter] postNotificationName:NTESNotificationLogout object:nil];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下线通知" message:reason delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: