參考網址: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
執行截圖:(基本功能實現,具體細節還需要優化)