当前位置: 首页 > 工具软件 > cl-xmpp > 使用案例 >

iOS 即时通讯之xmpp

华涵意
2023-12-01

 

//
//  ViewController.m
//  XMPP_lesson

//

//  Created by  王聪 on 14/8/20.

//  Copyright (c) 2015 Congwang. All rights reserved.
//

#import "ViewController.h"
#import "XMPPHelper.h"

@interface ViewController ()<XMPPStreamDelegate>
@property (weaknonatomicIBOutlet UITextField *userTF;//用户名TF
@property (weaknonatomicIBOutlet UITextField *passWordTF;//密码TF

@end

@implementation ViewController
//登陆方法
- (IBAction)loginAction:(UIButton *)sender {
    //发起登陆操作
    [[XMPPHelper sharedXMPPHelper]loginServerWithUserName:self.userTF.text password:self.passWordTF.text];
}
#pragma mark  --  密码验证成功回调方法
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
    [self performSegueWithIdentifier:@"segue" sender:nil];
}

//注册方法
- (IBAction)registerAction:(UIButton *)sender {
    [[XMPPHelper sharedXMPPHelperregisterServerWithUserName:self.userTF.text password:self.passWordTF.text];
}


- (void)viewDidLoad {
    [super viewDidLoad];
    //再把当前的对象添加为xmppStream的代理
    [[XMPPHelper sharedXMPPHelper].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
   
   
   
   
   
    // Do any additional setup after loading the view, typically from a nib.
}

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

@end

 

//
//  FriendListViewController.m
//  XMPP_lesson
//
//  Created by 王聪 on 15/8/21.
//  Copyright (c) 2015 Congwang. All rights reserved.
//

#import "FriendListViewController.h"
#import "XMPPHelper.h"
#import "ChatTableViewController.h"
@interface FriendListViewController ()<UITableViewDelegateUITableViewDataSourceXMPPRosterDelegateUIAlertViewDelegate>
@property (weaknonatomicIBOutlet UITableView *tableView;
//shujvyuan shuxing ,laizhanshixinxi
@property (strongnonatomic)NSMutableArray *dataSource;
@end

@implementation FriendListViewController
//添加好友
- (IBAction)addFriend:(UIBarButtonItem *)sender {
    UIAlertView *alertView = [[UIAlertView allocinitWithTitle:@"提示" message:@"添加好友" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定"nil];
    //设置alerView的样式, 带一个输入框
    alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
    [alertView show];
   
   
}
#pragma mark - alertView的代理方法
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    //如果点击的时确定
    if (buttonIndex) {
        //获取alertView上面输入框的值
        UITextField *alerTF = [alertView textFieldAtIndex:0];
        NSString *userName = alerTF.text;
        //封装成XMPPJID
        XMPPJID *friendJID = [XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
        //添加好友
        [[XMPPHelper sharedXMPPHelper].xmppRoster addUser:friendJID withNickname:nil];
       
    }
}




#pragma mark  -- tableView代理方法和dataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
   
    return self.dataSource.count;
   
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
   
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    XMPPJID *jid = self.dataSource[indexPath.row];
    cell.textLabel.text = jid.user;
    return cell;
   
   
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // 初始化数组
    self.dataSource = [NSMutableArray array];
   
    //添加当前对象为xmppRoster的代理对象
    [[XMPPHelper sharedXMPPHelper].xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    //调整视图的边距, 这个是ios7之后的方法, ios6不能用
    self.edgesForExtendedLayout = UIRectEdgeNone;
}
#pragma mark -- xmppRosterdelegate 的代理方法
//好友花名册开始检索好友的代理方法
-(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender{
   
   
}
//检索到好友信息的代理方法
- (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item{
    //xml解析中获取节点中的属性
    NSString *jidStr = [[item attributeForName:@"jid"stringValue];
    //xml解析获取节点中的订阅属性
    NSString *subscriptionStatus = [[item attributeForName:@"subscription"stringValue];
    if ([subscriptionStatus isEqualToString:@"both"]) {
        //封装成JID对象
        XMPPJID *friendJID = [XMPPJID jidWithString:jidStr resource:kResource];
       
        if ([self.dataSource containsObject:friendJID]) {
            return;
        }
       
        //插入数据源数组
        [self.dataSource addObject:friendJID];
       
        //再插单元格
        [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.dataSource.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationLeft];
        //tableView滚动
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataSource.count - 1 inSection:0atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }
}
//xmppRoster结束检索
- (void)xmppRosterDidEndPopulating:(XMPPRoster *)sender{
   
   
}






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


#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    ChatTableViewController *chatVC = segue.destinationViewController;
    //找到点击的cell
    UITableViewCell *cell = sender;
    //获取点击cell的下标
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    chatVC.friendJID = self.dataSource[indexPath.row];

   
   
   
}

 

@end

 

 

//
//  ChatTableViewController.h
//  XMPP_lesson
//
//  Created by 王聪 on 15/8/21.
//  Copyright (c) 2015 Congwang. All rights reserved.
//

#import <UIKit/UIKit.h>
@class XMPPJID;
@interface ChatTableViewController : UITableViewController
//声明当前聊天好友的JID属性
@property (nonatomicstrong)XMPPJID *friendJID;

@end

 

//
//  ChatTableViewController.m
//  XMPP_lesson
//
//  Created by lanouhn on 15/8/21.
//  Copyright (c) 2015 Congwang. All rights reserved.
//

#import "ChatTableViewController.h"
#import "XMPPHelper.h"

@interface ChatTableViewController ()<XMPPStreamDelegate>
@property (strongnonatomic)NSMutableArray *dataSource;
@end

@implementation ChatTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //添加当前为xmppStream的代理对象
    [[XMPPHelper sharedXMPPHelper].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
   
    //初始化数组
    self.dataSource = [NSMutableArray array];
    //调用检索本地聊天记录的方法
    [self seacherMessageBetweenFriend];
   
   
   
   
}
//检索本地聊天记录
- (void)seacherMessageBetweenFriend{
    NSManagedObjectContext *context = [XMPPHelper sharedXMPPHelper].managedContext;
   
    //创建查询请求对象
    NSFetchRequest *request = [[NSFetchRequest allocinitWithEntityName:@"XMPPMessageArchiving_Message_CoreDataObject"];
    //设置检索条件
    //1.创建谓词
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bareJidStr == %@ and streamBareJidStr == %@"self.friendJID.bare, [XMPPHelper sharedXMPPHelper].xmppStream.myJID.bare];
    request.predicate = predicate;
    //2.设置排序
    NSSortDescriptor *description = [[NSSortDescriptor allocinitWithKey:@"timestamp" ascending:YES];
    request.sortDescriptors = @[description];
    //执行这个查询请求
    NSArray *resultArray = [context executeFetchRequest:request error:nil];
   
    //加入数据源
    [self.dataSource addObjectsFromArray:resultArray];
    //刷新单元格
    [self.tableView reloadData];
   
   
   
}






//发送消息的方法
- (IBAction)sendMessage:(UIBarButtonItem *)sender {
   
   
    //创建消息对象
    XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.friendJID];
    //给消息添加内容
    [message addBody:@"你懂得http://cl.ttum.pw/htm_data/7/1508/1607032.html"];
    //3. *发送消息
    [[XMPPHelper sharedXMPPHelper].xmppStream sendElement:message];
   
}



- (void)showNewMessage:(XMPPMessage *)message{
    //插入数据源
    [self.dataSource addObject:message];
    //插入单元格
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataSource.count - 1 inSection:0];
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
    //tableView
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
#pragma mark -- 与聊天相关的xmppStream的代理回调方法
//收到消息的代理回调
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{
    //判断消息发送者
    XMPPJID *friendJID = message.from;
    if ([self.friendJID isEqualToJID:friendJID]) {
        [self showNewMessage:message];
    }
   
   
}
//发送消息成功的代理回调方法
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{
   
    [self showNewMessage:message];
}

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

#pragma mark - Table view data source

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
   
    return self.dataSource.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cells" forIndexPath:indexPath];
    XMPPMessage *message = self.dataSource[indexPath.row];
   
    if ([message isKindOfClass:[XMPPMessage class]]) {
        if ([message.from isEqualToJID:self.friendJID]) {
            cell.textLabel.textColor = [UIColor redColor];
        }else{
            cell.textLabel.textColor = [UIColor blackColor];
        }
        cell.textLabel.text = message.body;
         return cell;
    }
    else{
       
        XMPPMessageArchiving_Message_CoreDataObject *message = self.dataSource[indexPath.row];
        //判断消息是不是登录用户发送的(isOutdoing是自己发送的)
        if (![message isOutgoing]) {
            cell.textLabel.textColor = [UIColor redColor];
        }else{
            cell.textLabel.textColor = [UIColor blackColor];
        }
        cell.textLabel.text = message.body;
        return cell;

       
    }
    }
   
   
   
   
   
   
   
   
  
  



/*
 // Override to support conditional editing of the table view.
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
 // Return NO if you do not want the specified item to be editable.
 return YES;
 }
 */


/*
 // Override to support editing the table view.
 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
 if (editingStyle == UITableViewCellEditingStyleDelete) {
 // Delete the row from the data source
 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
 } else if (editingStyle == UITableViewCellEditingStyleInsert) {
 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
 }
 }
 */


/*
 // Override to support rearranging the table view.
 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
 }
 */


/*
 // Override to support conditional rearranging of the table view.
 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
 // Return NO if you do not want the item to be re-orderable.
 return YES;
 }
 */


/*
 #pragma mark - Navigation
 
 // In a storyboard-based application, you will often want to do a little preparation before navigation
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
 // Get the new view controller using [segue destinationViewController].
 // Pass the selected object to the new view controller.
 }
 */

 

@end

 

 

 

//
//  XMPPHelper.h
//  XMPP_lesson
//
//  Created by lanouhn on 15/8/20.
//  Copyright (c) 2015 Congwang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "XMPPFramework.h"
@interface XMPPHelper : NSObject<XMPPStreamDelegateXMPPRosterDelegate>

//通信介质(管道对象), 在整个xmpp框架中非常重要, 所有的服务都是建立在它之上
@property (nonatomicstrong)XMPPStream *xmppStream;
//声明好友花名册属性 (负责所有与好友相关的操作)
@property (nonatomicstrongXMPPRoster *xmppRoster;
//声明消息归档对象 (这个对象负责消息的归档)
@property (nonatomicstrong)XMPPMessageArchiving *messageArchiving;
//声明被管理对象上下文, 方便外界查询 (因为我们要查询聊天记录)
@property (strong , nonatomic)NSManagedObjectContext *managedContext;

+ (XMPPHelper *)sharedXMPPHelper;
//1.登陆方法
- (void)loginServerWithUserName:(NSString *)userName password:(NSString *)password;

//2.注册方法
- (void)registerServerWithUserName:(NSString *)userName password:(NSString *)password;

 

 

@end

 

 

//
//  XMPPHelper.m
//  XMPP_lesson
//
//  Created by 王聪 on 15/8/20.
//  Copyright (c) 2015 Congwang. All rights reserved.
//

#import "XMPPHelper.h"
#import "FriendListViewController.h"

//定义枚举
typedef NS_ENUM(NSInteger, ThePurposeOfLinkServer)
{
    LoginPurpose = 0,
    RegisterPurpose = 1
};

//延展
@interface XMPPHelper ()
//声明密码属性, 用于验证密码的验证
@property (nonatomic, copy)NSString *password;
//声明枚举属性来区分登陆和注册
@property (nonatomic, assign)ThePurposeOfLinkServer purpose;

@end



@implementation XMPPHelper
//xmpp服务助手
+ (XMPPHelper *)sharedXMPPHelper{
    static XMPPHelper *xmppHelper = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        xmppHelper = [[XMPPHelper allocinit];
    });
    return xmppHelper;
}
//重写init方法, 在该方法中完成一些xmpp中一些类的基本设置
-(instancetype)init{
    self = [super init];
    if (self) {
        //1.xmppStream的设置
        //1.1创建xmppStream对象
        self.xmppStream = [[XMPPStream allocinit];
        //指定xmppStream链接的服务器的地址
        self.xmppStream.hostName = kHostName;
        //指定xmppStream链接服务器的端口号
        self.xmppStream.hostPort = kHostPort;
        //添加xmppStream的代理对象
        //1.指定代理对象
        //2.指定GCD队列, 我们选择主线程
        [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
       
       
        //完成xmppRoster的一些基本配置
       
        //1.创建好友存储对象
        XMPPRosterCoreDataStorage *storage = [XMPPRosterCoreDataStorage sharedInstance];
        //2.创建好友花名册管理对象
        self.xmppRoster = [[XMPPRoster allocinitWithRosterStorage:storage dispatchQueue:dispatch_get_main_queue()];
        //3.添加代理
        [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
        //4.* 打开xmppRoster服务
        [self.xmppRoster activate:self.xmppStream];
       
        //创建消息存储对象
        XMPPMessageArchivingCoreDataStorage *archivingStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
        //给数据管理器属性赋值, 方便外界的访问
        self.managedContext =  archivingStorage.mainThreadManagedObjectContext;
        //创建信息归档对象
        self.messageArchiving = [[XMPPMessageArchiving allocinitWithMessageArchivingStorage:archivingStorage dispatchQueue:dispatch_get_main_queue()];
        //添加代理, 不用遵守代理协议
        [self.messageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()];
        //**启动该服务
        [self.messageArchiving activate:self.xmppStream];
       
   
       
       
    }return self;
   
}

//发起请求方法
- (void)connectToServer{
    if (self.xmppStream.isConnected || self.xmppStream.isConnecting) {
        //告诉服务器我们xia线了
        //1.创建XMPPPresence对象,unavailable就是xia线了
        XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
        //2.发送xia线状态
        [self.xmppStream sendElement:presence];
        //断开链接
        [self.xmppStream disconnect];
    }
    //发起链接请求
    [self.xmppStream connectWithTimeout:-1 error:nil];
}





/**
 * 
 登陆方法的实现
 */
- (void)loginServerWithUserName:(NSString *)userName password:(NSString *)password{
    //给密码属性赋值
    self.password = password;
    //geimudi meijv fuzhi
    self.purpose = LoginPurpose;
    // 登陆方法
    //1.创建登陆方
    XMPPJID *userJID = [XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
    //2.告诉xmppStream登陆方是谁
    self.xmppStream.myJID = userJID;
   
    //发起链接请求
    [self connectToServer];
   
}
/**
 * 
 注册方法的实现
 */

- (void)registerServerWithUserName:(NSString *)userName password:(NSString *)password{
    //给密码赋值
    self.password = password;
    //给目的属性赋值
    self.purpose = RegisterPurpose;
   
   
    //注册第一步
    //1.创建注册方法
    XMPPJID *registerUser = [XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
    //2.谁在注册
    self.xmppStream.myJID = registerUser;
    //3.发起注册
    [self connectToServer];
   
}
#pragma mark  -- xmppStream的代理方法
//管道对象将要链接的时候出发
- (void)xmppStreamWillConnect:(XMPPStream *)sender{
   
    NSLog(@"%s, %d",__FUNCTION__, __LINE__ );
   
}
//xmppStream基于的socket管道链接上的时候触发
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket{
   
    NSLog(@"%s, %d",__FUNCTION__, __LINE__ );
}
//管道对象已经链接上出发的方法
- (void)xmppStreamDidConnect:(XMPPStream *)sender{
   
   
    if (!self.purpose) {
        //验证密码
        [self.xmppStream authenticateWithPassword:self.password error:nil];
    }else{
        //注册账号
        [self.xmppStream registerWithPassword:self.password error:nil];
    }
    NSLog(@"%s, %d",__FUNCTION__, __LINE__ );
}

//对该账号进行验证

//验证成功的方法
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender{
    //告诉服务器我们上线了
    //1.创建XMPPPresence对象,available就是上线了
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
    //2.发送上线状态
    [self.xmppStream sendElement:presence];
   
    //提示框
    UIAlertView *alertView = [[UIAlertView allocinitWithTitle:@"提示" message:@"登陆成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
    NSLog(@"成功");
   
   
   
   
   
   
   
}
//验证失败的方法
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{
    //提示框
    UIAlertView *alertView = [[UIAlertView allocinitWithTitle:@"提示" message:@"登陆失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
    NSLog(@"失败");
}

//注册账号的方法
//注册成功的方法
- (void)xmppStreamDidRegister:(XMPPStream *)sender{
    UIAlertView *alertView = [[UIAlertView allocinitWithTitle:@"提示" message:@"注册成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
}
//注册失败的方法
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{
    UIAlertView *alertView = [[UIAlertView allocinitWithTitle:@"提示" message:@"注册失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
}

#pragma mark -- xmppRoster代理方法
//接收到好友的添加请求
- (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence{
    //获取请求添加好友的JID
    XMPPJID *friendJID = presence.from;
   
    //我们同意添加为好友
    [self.xmppRoster acceptPresenceSubscriptionRequestFrom:friendJID andAddToRoster:YES];
   
   
//    //拒绝好友的添加请求
//    [self.xmppRoster rejectPresenceSubscriptionRequestFrom:friendJID];
   
   
   
   
}





@end

 

 

 

 类似资料: