xmpp實現的即時通訊聊天(二)

有稜角的圓發表於2016-08-25

參考網址:http://www.jianshu.com/p/8894a5a71b70

借圖描述原理:

三、註冊、登陸、聊天功能的實現

故事板如下:

四個類如下:

不喜多言,直接上Demo:

LoginViewController.h

#import "ViewController.h"
#import "XMPPManager.h"
#import "RosterViewController.h"
@interface LoginViewController : ViewController<XMPPStreamDelegate>

@end

 

LoginViewController.m

#import "LoginViewController.h"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
   [[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
}
- (IBAction)login:(UIButton *)sender {
    NSLog(@"Click login button");
    if (self.usernameTextField.text.length>0&&self.passwordTextField.text.length>0) {
        
        [[XMPPManager defaultManager] loginwithName:self.usernameTextField.text andPassword:self.passwordTextField.text];
    }
}
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
    NSLog(@"登陸成功");
    RosterViewController *roster=[RosterViewController new];
    [self.navigationController pushViewController:roster animated:YES];
    
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

RegisterViewController.h

#import "ViewController.h"
#import "XMPPManager.h"
@interface RegisterViewController : ViewController<XMPPStreamDelegate>

@end

 

RegisterViewController.m


#import "RegisterViewController.h"

@interface RegisterViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameTextfield;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextfield;

@end

@implementation RegisterViewController
- (IBAction)register:(UIButton *)sender {
    [[XMPPManager defaultManager] registerWithName:self.usernameTextfield.text andPassword:self.passwordTextfield.text];
}
- (IBAction)cancel:(UIButton *)sender {
    [self.navigationController popViewControllerAnimated:YES];
}
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
    
    NSLog(@"註冊成功!!");
    
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
}

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

RosterViewController.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "ViewController.h"
#import "XMPPManager.h"
#import "ChatViewController.h"
@interface RosterViewController : ViewController<UITableViewDataSource,UITableViewDelegate,XMPPRosterDelegate>
//存放所有好友的陣列
@property(nonatomic,strong) NSMutableArray *rosterJids;

@property(nonatomic,strong) UITableView *friendsView;


@end

 

RosterViewController.m


#import "RosterViewController.h"

@interface RosterViewController ()

@end

@implementation RosterViewController


-(UITableView*)friendsView{
    if (_friendsView==nil) {
        _friendsView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
        _friendsView.dataSource=self;
        _friendsView.delegate=self;
    }
    return _friendsView;
}

#pragma mark friendView 代理方法

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    if (self.rosterJids.count>0) {
        return self.rosterJids.count;
    }
    return 0;
    
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *ide=@"cell";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ide];
    if (cell==nil) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ide];
    }
    XMPPJID *jid = self.rosterJids[indexPath.row];
    cell.textLabel.text=jid.user;
    return cell;
}
#pragma mark 刪除好友執行的方法
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
    if (editingStyle==UITableViewCellEditingStyleDelete) {
        //找到要刪除的人
        XMPPJID *jid = self.rosterJids[indexPath.row];
        //從陣列中刪除
        [self.rosterJids removeObjectAtIndex:indexPath.row];
        //從Ui單元格刪除
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic         ];
        //從伺服器刪除
        [[XMPPManager defaultManager].xmppRoster removeUser:jid];
    }
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    ChatViewController *chatVC=[ChatViewController new];
    chatVC.chatToJid=self.rosterJids[indexPath.row];
    [self.navigationController pushViewController:chatVC animated:YES];
}


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.rosterJids = [[NSMutableArray alloc]init];
    [[XMPPManager defaultManager].xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    //
    UIBarButtonItem *right=[[UIBarButtonItem alloc]initWithTitle:@"新增" style:UIBarButtonItemStylePlain target:self action:@selector(doAdd:)];
    self.navigationItem.rightBarButtonItem = right;
    [self.view addSubview:self.friendsView];
    
}

//點選新增好友
-(void)doAdd:(UIButton*)sender{
    XMPPJID *jid= [XMPPJID jidWithUser:@"admin" domain:@"" resource:nil];
    //新增好友
    [[XMPPManager defaultManager].xmppRoster subscribePresenceToUser:jid];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//#pragma mark XMPPRoster 的代理方法

#pragma mark 開始檢索好友列表的方法
-(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender{
    NSLog(@"開始檢索好友列表");
}
#pragma mark 正在檢索好友列表的方法
-(void)xmppRoster:(XMPPRoster *)sender didRecieveRosterItem:(DDXMLElement *)item{
    NSLog(@"每一個好友都會走一次這個方法");
    //獲得item的屬性裡的jid字串,再通過它獲得jid物件
    NSString *jidStr = [[item attributeForName:@"jid"] stringValue];    XMPPJID *jid = [XMPPJID jidWithString:jidStr];
    //是否已經新增
    if ([self.rosterJids containsObject:jid]) {
        return;
    }
    //將好友新增到陣列中去
    [self.rosterJids addObject:jid];
    //新增完資料要更新UI(表檢視更新)
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.rosterJids.count-1 inSection:0];
    
    [self.friendsView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

@end

ChatViewController.h

#import "ViewController.h"
#import "XMPPManager.h"
@interface ChatViewController : ViewController<XMPPStreamDelegate,UITableViewDataSource,UITableViewDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>

@property(nonatomic,strong) XMPPJID *chatToJid;

@property(nonatomic,retain) NSMutableArray *messages;

@property(nonatomic,strong) UITableView *tableView;


@end

 

ChatViewController.m


#import "ChatViewController.h"

@interface ChatViewController ()

@end

@implementation ChatViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title=self.chatToJid.user;
    self.view.backgroundColor=[UIColor grayColor];
    //初始化聊天陣列
    self.messages=[[NSMutableArray alloc]init];
    //設定代理
    [[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    //
    [self reloadMessage];
    //
    UIBarButtonItem *sendMessage=[[UIBarButtonItem alloc]initWithTitle:@"傳送" style:UIBarButtonItemStylePlain target:self action:@selector(doSend)];
    self.navigationItem.rightBarButtonItem=sendMessage;
    [self.view addSubview:self.tableView];
}
-(void)doSend{
    /*
    //建立一個訊息物件,並且指明接收者
    XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJid];
    //設定訊息內容
    [message addBody:@"呵呵呵呵呵呵呵呵呵呵啊啊啊啊啊啊"];
    //傳送訊息
    [[XMPPManager defaultManager].xmppStream sendElement:message];
    //傳送成功或者失敗,有兩種對應的代理方法
    */
    
    UIImagePickerController *pick=[[UIImagePickerController alloc]init];
    pick.delegate=self;
    [self presentViewController:pick animated:YES completion:^{
        
    }];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
    //獲取相簿裡的圖片
    //UIImage *image=info[UIImagePickerControllerOriginalImage];
    UIImage *image=[UIImage imageNamed:@"1.png"];

    //轉化成NSData
    NSData *data=UIImagePNGRepresentation(image);
    //傳送
    [self sendImageWithData:data andName:@"圖片"];
    
    //
    [self dismissViewControllerAnimated:YES completion:nil];
}
-(void)sendImageWithData:(NSData*)data andName:(NSString*)name{
    XMPPMessage *message= [XMPPMessage messageWithType:@"chat" to:self.chatToJid];
    [message addBody:name];
    //
    NSString *base64Str=[data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    //
    XMPPElement *attachment=[XMPPElement elementWithName:@"attachment" stringValue:base64Str];
    //
    
    [message addChild:attachment];
    //
    [[XMPPManager defaultManager].xmppStream sendElement:message];
}
-(UITableView*)tableView{
    if (!_tableView) {
        _tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 300, self.view.frame.size.height) style:UITableViewStylePlain];
        _tableView.dataSource=self;
        _tableView.delegate=self;
    }
    
    return _tableView;
}
#pragma tableView delegate
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.messages.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    return 100;

}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //NSLog(@"cell");
    static NSString *cellIndentifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier];
    if (cell==nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIndentifier];
    }
    //將聊天資訊放到cell上
    //拿到一個聊天訊息
    XMPPMessageArchiving_Message_CoreDataObject *message = self.messages[indexPath.row];
    XMPPMessage *msg=message.message;
        if (message.isOutgoing == YES) {
        cell.detailTextLabel.text = message.body;
        cell.textLabel.text=@"";
            for(XMPPElement *node in msg.children){
                NSLog(@"圖片呢");
                //取出訊息
                NSString *base64Str=node.stringValue;
                //NSLog(@"%@",base64Str);
                //base64轉換成NSData
                NSData *data=[[NSData alloc]initWithBase64EncodedString:base64Str options:1];
                UIImage *image=[[UIImage alloc]initWithData:data];
                cell.imageView.image=image;
                cell.imageView.frame=CGRectMake(0, 0, 50, 50);
                cell.imageView.backgroundColor=[UIColor redColor];
            }

    }else{
        cell.textLabel.text = message.body;
        cell.detailTextLabel.text=@"";
    }
   // cell.imageView.backgroundColor=[UIColor redColor];
  //  cell.imageView.image=[UIImage imageNamed:@"1.png"];
    return cell;

}
    


#pragma mark 聊天的代理方法
-(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{
    
    NSLog(@"訊息傳送成功");
    [self reloadMessage];
}
-(void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error{
    NSLog(@"訊息傳送失敗");
}
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{
    
    NSLog(@"訊息接受成功");
    [self reloadMessage];
}
-(void)xmppStream:(XMPPStream *)sender didReceiveError:(DDXMLElement *)error{
    NSLog(@"接收失敗");
}
#pragma mark 重新整理訊息的方法
-(void)reloadMessage{
    //得到上下文
    NSManagedObjectContext *context = [XMPPManager defaultManager].messageArchivingContext;
    //搜尋物件
    NSFetchRequest *request = [[NSFetchRequest alloc]init];
    //建立一個實體描述
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context];
    [request setEntity:entity];
    //查詢條件
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@ AND bareJidStr = %@",[XMPPManager defaultManager].xmppStream.myJID.bare,self.chatToJid.bare];
    request.predicate = pre;
    //排序方式
    NSSortDescriptor *sort = [[NSSortDescriptor alloc]initWithKey:@"timestamp" ascending:YES];
    request.sortDescriptors = @[sort];
    //執行查詢
    NSError *error = nil;
    NSArray *array = [context executeFetchRequest:request error:&error];    if (self.messages.count != 0) {
        [self.messages removeAllObjects];
    }
    [self.messages addObjectsFromArray:array];
    [self.tableView reloadData];
    if (self.messages.count>0) {
        NSIndexPath *indexpath=[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0];
        
        [self.tableView scrollToRowAtIndexPath:indexpath atScrollPosition:UITableViewScrollPositionTop animated:YES];
        
    }
    
}

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



@end

執行截圖:(基本功能實現,具體細節還需要優化)

相關文章