環(huán)信

-------------------AppDelegate.m-------------------

#import "AppDelegate.h"

// 環(huán)信的頭文件
#import <EaseMob.h>

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 注冊環(huán)信SDK
    // 第一個參數(shù) :APPkey 由應(yīng)用名字#公司的ID構(gòu)成
    // 第二個參數(shù) :如果使用推送功能 則需要填推送證書的名字
    [[EaseMob sharedInstance] registerSDKWithAppKey:@"lutianyi#easemobsample" apnsCertName:@""];
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
// App進(jìn)入后臺
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[EaseMob sharedInstance] applicationDidEnterBackground:application];
}
// App將要從后臺返回
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[EaseMob sharedInstance] applicationWillEnterForeground:application];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
// 申請?zhí)幚頃r間
- (void)applicationWillTerminate:(UIApplication *)application
{
    [[EaseMob sharedInstance] applicationWillTerminate:application];
    [self saveContext];
}

----------------LoginViewController.m----------------

#import "LoginViewController.h"

#import "RegisterViewController.h"
#import "MessageViewController.h"
#import "RosterViewController.h"
#import "AppDelegate.h"
#import <EaseMob.h>

@interface LoginViewController ()

@property (weak, nonatomic) IBOutlet UITextField *userNameTextField;
@property (weak, nonatomic) IBOutlet UITextField *passWordTextField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;
@property (weak, nonatomic) IBOutlet UIButton *registerButton;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.userNameTextField.layer.borderWidth = 1;
    self.passWordTextField.layer.borderWidth = 1;
    
}

- (IBAction)loginButtonClicked:(id)sender
{
    [[EaseMob sharedInstance].chatManager asyncLoginWithUsername:self.userNameTextField.text password:self.passWordTextField.text completion:^(NSDictionary *loginInfo, EMError *error)
    {
        if (!error)
        {
            NSLog(@"登錄成功");
            MessageViewController *messageVC = [MessageViewController new];
            UINavigationController *messageNC = [[UINavigationController alloc] initWithRootViewController:messageVC];
            messageNC.title = @"消息";
            
            RosterViewController *rosterVC = [RosterViewController new];
            UINavigationController *rosterNC = [[UINavigationController alloc] initWithRootViewController:rosterVC];
            rosterNC.title = @"好友";
            
            UITabBarController *tabBar = [UITabBarController new];
            tabBar.viewControllers = @[messageNC, rosterNC];
            
            AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
            app.window.rootViewController = tabBar;
        }
        else
        {
            NSLog(@"登錄失敗  error ==== %@", error);
        }
    } onQueue:dispatch_get_main_queue()];
}
- (IBAction)registerButtonClicked:(id)sender
{
    RegisterViewController *registerVC = [RegisterViewController new];
    registerVC = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"registerVC"];
    [self showViewController:registerVC sender:nil];
    
    __weak typeof(self) pSelf = self;
    registerVC.passValue = ^(NSString *userName, NSString *passWord)
    {
        pSelf.userNameTextField.text = userName;
        pSelf.passWordTextField.text = passWord;
    };
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

----------------RegisterViewController.h--------------

#import <UIKit/UIKit.h>

typedef void(^myBlock)(NSString *, NSString *);

@interface RegisterViewController : UIViewController

@property (nonatomic, copy)myBlock passValue;

@end

---------------RegisterViewController.m--------------

#import "RegisterViewController.h"

#import <EaseMob.h>

@interface RegisterViewController ()

@property (weak, nonatomic) IBOutlet UITextField *userNameTextField;
@property (weak, nonatomic) IBOutlet UITextField *passWordTextField;
@property (weak, nonatomic) IBOutlet UIButton *registerButton;

@end

@implementation RegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.userNameTextField.layer.borderWidth = 1;
    self.passWordTextField.layer.borderWidth = 1;
    
}

- (IBAction)registerButtonClicked:(id)sender
{
    [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:self.userNameTextField.text password:self.passWordTextField.text withCompletion:^(NSString *username, NSString *password, EMError *error)
    {
        if (!error)
        {
            NSLog(@"注冊成功");
            self.passValue(self.userNameTextField.text, self.passWordTextField.text);
            [self dismissViewControllerAnimated:YES completion:nil];
        }
        else
        {
            NSLog(@"注冊失敗 error === %@", error);
        }
    } onQueue:dispatch_get_main_queue()];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

---------------MessageViewController.m--------------

#import "MessageViewController.h"

#import "ChatViewController.h"
#import <EaseMob.h>

@interface MessageViewController ()<UITableViewDataSource, UITableViewDelegate, EMChatManagerDelegate>

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataArray;

@end

@implementation MessageViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"最新消息";
    
    self.dataArray = [NSMutableArray array];
    self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
}
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:dispatch_get_main_queue()];
    [self reloadConversation];
}
// 收到一條消息
- (void)didReceiveMessage:(EMMessage *)message
{
    [self reloadConversation];
}

// 獲取數(shù)據(jù) 獲取當(dāng)前用戶的會話列表
- (void)reloadConversation
{
    [self.dataArray removeAllObjects];
    [self.dataArray addObjectsFromArray:[[EaseMob sharedInstance].chatManager loadAllConversationsFromDatabaseWithAppend2Chat:YES]];
    [self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];
    if (!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:@"CELL"];
    }
    
    // 聊天會話對象
    EMConversation *conversation = self.dataArray[indexPath.row];
    // chatter 會話對象中的名字
    cell.textLabel.text = conversation.chatter;
    
    // message 聊天消息對象 conversation.latestMessage 最后一條消息
    EMMessage *message = conversation.latestMessage;
    // EMTextMessageBody 消息體對象狞谱,message.messageBodies 聊天消息中保存的消息體對象
    // 獲取到最后一次發(fā)送的消息
    EMTextMessageBody *body = message.messageBodies.lastObject;
    cell.detailTextLabel.text = body.text;
    return cell;
}

- (void)didReceiveBuddyRequest:(NSString *)username message:(NSString *)message
{
    NSString *title = [NSString stringWithFormat:@"請求添加您為好友"];
    UIAlertController *controller = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
    {
        // 環(huán)信的錯誤類 相當(dāng)于NSError
        EMError *error = nil;
        BOOL succeed = [[EaseMob sharedInstance].chatManager acceptBuddyRequest:username error:&error];
        if (succeed && !error)
        {
            NSLog(@"接受成功");
        }
        else
        {
            NSLog(@"接收好友請求失敗乃摹,error ==== %@", error);
        }
    }];
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"殘忍拒絕" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
    {
        // 環(huán)信的錯誤類 相當(dāng)于NSError
        EMError *error = nil;
        BOOL succeed = [[EaseMob sharedInstance].chatManager rejectBuddyRequest:username reason:@"我拒絕" error:&error];
        if (succeed && !error)
        {
            NSLog(@"拒絕成功");
        }
        else
        {
            NSLog(@"拒絕好友請求失敗,error ==== %@", error);
        }
    }];
    [controller addAction:action];
    [controller addAction:action1];
    [self presentViewController:controller animated:YES completion:nil];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    ChatViewController *chatVC = [ChatViewController new];
    
    EMConversation *conversation = self.dataArray[indexPath.row];
    // chatter 會話對象的用戶名
    chatVC.chatter = conversation.chatter;
    
    [self showViewController:chatVC sender:nil];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

---------------RosterViewController.m----------------

#import "RosterViewController.h"

#import "AddFriendsViewController.h"
#import "ChatViewController.h"
#import <EaseMob.h>

@interface RosterViewController ()<UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataArray;

@end

@implementation RosterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"好友列表";
    
    self.dataArray = [NSMutableArray array];
    self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
    
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CELL"];
    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonClicked)];
}
- (void)addButtonClicked
{
    AddFriendsViewController *addFriendsVC = [AddFriendsViewController new];
    addFriendsVC = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"addFriendsVC"];
    [self presentViewController:addFriendsVC animated:YES completion:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self reloadRoster];
}
- (void)reloadRoster
{
    [self.dataArray removeAllObjects];
    [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {
        [self.dataArray removeAllObjects];
        [self.dataArray addObjectsFromArray:buddyList];
        [self.tableView reloadData];
    } onQueue:dispatch_get_main_queue()];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];
    // EMBuddy 好友的信息描述類
    EMBuddy *buddy = self.dataArray[indexPath.row];
    // username 好友名字
    cell.textLabel.text = buddy.username;
    return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    ChatViewController *chatVC = [[ChatViewController alloc] init];
    EMBuddy *buddy = self.dataArray[indexPath.row];
    chatVC.chatter = buddy.username;
    [self showViewController:chatVC sender:nil];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

----------------ChatViewController.h----------------

#import <UIKit/UIKit.h>

@interface ChatViewController : UIViewController

@property (nonatomic, copy) NSString *chatter;

@end

----------------ChatViewController.m----------------

#import "ChatViewController.h"

#import <EaseMob.h>

@interface ChatViewController ()<UITableViewDataSource, UITableViewDelegate, EMChatManagerDelegate>

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) EMConversation *conversation;

@end

@implementation ChatViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(sendMessage)];
    
    [self reloadMessage];
}

-(void)reloadMessage
{
    self.conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.chatter conversationType:eConversationTypeChat];
    [self.tableView reloadData];
}

- (void)sendMessage
{
    UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"發(fā)送消息" message:nil preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
    {
        
    }];
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"發(fā)送" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
    {
        // 聊天的文本對象
        EMChatText *text = [[EMChatText alloc] initWithText:controller.textFields.firstObject.text];
        // 聊天的文本消息體對象
        EMTextMessageBody *textMessageBody = [[EMTextMessageBody alloc] initWithChatObject:text];
        // 聊天消息類
        EMMessage *message = [[EMMessage alloc] initWithReceiver:self.chatter bodies:@[textMessageBody]];
        // 發(fā)送這條消息
        [[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil prepare:^(EMMessage *message, EMError *error)
        {
            // 準(zhǔn)備發(fā)送
        } onQueue:dispatch_get_main_queue() completion:^(EMMessage *message, EMError *error)
        {
            // 發(fā)送成功
            if (!error)
            {
                [self reloadMessage];
            }
        } onQueue:dispatch_get_main_queue()];
    }];
    [controller addAction:action];
    [controller addAction:action1];
    [controller addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        
    }];
    [self presentViewController:controller animated:YES completion:nil];
}
- (void)didReceiveMessage:(EMMessage *)message
{
    [self reloadMessage];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.conversation.loadAllMessages.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];
    if (!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"CELL"];
    }
    // 每一個message表示一條聊天記錄
    EMMessage *message = self.conversation.loadAllMessages[indexPath.row];
    // EMTextMessageBody 表示聊天的信息
    EMTextMessageBody *body = [message.messageBodies lastObject];
    // message.to 表示聊天的對象
    if ([message.to isEqualToString:self.chatter])
    {
        cell.textLabel.text = body.text;
        cell.detailTextLabel.text = @"";
    }
    else
    {
        cell.textLabel.text = @"";
        cell.detailTextLabel.text = body.text;
    }
    return cell;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

--------------AddFriendsViewController.m-------------

#import "AddFriendsViewController.h"

#import <EaseMob.h>

@interface AddFriendsViewController ()

@property (weak, nonatomic) IBOutlet UITextField *userNameTextField;
@property (weak, nonatomic) IBOutlet UIButton *addFriendsButton;

@end

@implementation AddFriendsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.userNameTextField.layer.borderWidth = 1;
    
}
- (IBAction)addFriendsButtonClicked:(id)sender
{
    EMError *error = nil;
    BOOL succeed = [[EaseMob sharedInstance].chatManager addBuddy:self.userNameTextField.text message:@"加一下好友跟衅,可以么孵睬?" error:&error];
    if (succeed && !error)
    {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    else
    {
        NSLog(@"error ==== %@", error);
    }
    
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end
Main.storyboard

工程截圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市与斤,隨后出現(xiàn)的幾起案子肪康,更是在濱河造成了極大的恐慌,老刑警劉巖撩穿,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磷支,死亡現(xiàn)場離奇詭異,居然都是意外死亡食寡,警方通過查閱死者的電腦和手機雾狈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抵皱,“玉大人善榛,你說我怎么就攤上這事∩牖” “怎么了移盆?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長伤为。 經(jīng)常有香客問我咒循,道長,這世上最難降的妖魔是什么绞愚? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任叙甸,我火速辦了婚禮,結(jié)果婚禮上位衩,老公的妹妹穿的比我還像新娘裆蒸。我一直安慰自己,他們只是感情好糖驴,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布僚祷。 她就那樣靜靜地躺著,像睡著了一般贮缕。 火紅的嫁衣襯著肌膚如雪久妆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天跷睦,我揣著相機與錄音筷弦,去河邊找鬼。 笑死抑诸,一個胖子當(dāng)著我的面吹牛烂琴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜕乡,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼奸绷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了层玲?” 一聲冷哼從身側(cè)響起号醉,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤反症,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后畔派,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铅碍,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年线椰,在試婚紗的時候發(fā)現(xiàn)自己被綠了胞谈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡憨愉,死狀恐怖烦绳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情配紫,我是刑警寧澤径密,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站躺孝,受9級特大地震影響睹晒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜括细,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一伪很、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奋单,春花似錦锉试、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贷笛,卻和暖如春应又,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乏苦。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工株扛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人汇荐。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓洞就,卻偏偏與公主長得像,于是被迫代替她去往敵國和親掀淘。 傳聞我的和親對象是個殘疾皇子旬蟋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 一、準(zhǔn)備工作 1革娄、注冊環(huán)信帳號注冊一個環(huán)信賬號之后倾贰,我們用注冊的帳號登陸冕碟。然后創(chuàng)建一個應(yīng)用,會得到一個對應(yīng)的App...
    niceSYT閱讀 415評論 1 2
  • 一匆浙、準(zhǔn)備工作 1安寺、注冊環(huán)信帳號 注冊一個環(huán)信賬號之后,我們用注冊的帳號登陸吞彤。然后創(chuàng)建一個應(yīng)用我衬,會得到一個對應(yīng)的Ap...
    樊二哈閱讀 1,302評論 1 10
  • 第一次集成環(huán)信SDK應(yīng)該是在去年吧叹放,那個時候還是2.0的版本饰恕,沒想到后面做的幾個APP都用到了環(huán)信的及時聊天,用過...
    imGeek閱讀 1,628評論 4 16
  • 版權(quán)聲明:本文為博主原創(chuàng)文章井仰,未經(jīng)博主允許不得轉(zhuǎn)載埋嵌。 前言 公司最近要求做即時通訊, 直接用了三方環(huán)信了,今天和大...
    Heaven7th閱讀 9,650評論 24 30
  • 柯特科本活著的時候我從未聽過他的歌雹嗦,在1997年敦煌音像出版社同時引進(jìn)了never mind和Mtv不插電演唱會兩...
    觸摸音樂閱讀 385評論 1 0