參考網址:http://www.jianshu.com/p/8894a5a71b70node
借圖描述原理:數組
3、註冊、登錄、聊天功能的實現服務器
故事板以下:dom
四個類以下:ide
不喜多言,直接上Demo:優化
LoginViewController.hatom
#import "ViewController.h" #import "XMPPManager.h" #import "RosterViewController.h" @interface LoginViewController : ViewController<XMPPStreamDelegate> @end
LoginViewController.mspa
#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.h3d
#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
運行截圖:(基本功能實現,具體細節還須要優化)