• xmpp实现的即时通讯聊天(二)


    参考网址: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

    运行截图:(基本功能实现,具体细节还需要优化)

  • 相关阅读:
    使用C# (.NET Core) 实现模板方法模式 (Template Method Pattern)
    使用C# (.NET Core) 实现单体设计模式 (Singleton Pattern)
    使用C# (.NET Core) 实现抽象工厂设计模式 (Abstract Pattern)
    使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)
    使用 dynamic 类型让 ASP.NET Core 实现 HATEOAS 结构的 RESTful API
    使用静态基类方案让 ASP.NET Core 实现遵循 HATEOAS Restful Web API
    .NET Core/.NET之Stream简介
    使用C# (.NET Core) 实现装饰模式 (Decorator Pattern) 并介绍 .NET/Core的Stream
    MySQL 导入数据
    MySQL 导出数据
  • 原文地址:https://www.cnblogs.com/sunjianfei/p/5806806.html
Copyright © 2020-2023  润新知