接上一章的,這一章我們著重介紹XMPP
為了方便程式調用,我們把XMPP的一些主要方法寫在AppDelegate中
在AppDelegate.m下這幾個方法為:
-(void)setupStream{ //初始化XMPPStream xmppStream = [[XMPPStream alloc] init]; [xmppStream addDelegate:self delegateQueue:dispatch_get_current_queue()]; }-(void)goOnline{ //發送線上狀態 XMPPPresence *presence = [XMPPPresence presence]; [[self xmppStream] sendElement:presence]; }-(void)goOffline{ //發送下線狀態 XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"]; [[self xmppStream] sendElement:presence]; }-(BOOL)connect{ [self setupStream]; //從本地取得使用者名稱,密碼和伺服器位址 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *userId = [defaults stringForKey:USERID]; NSString *pass = [defaults stringForKey:PASS]; NSString *server = [defaults stringForKey:SERVER]; if (![xmppStream isDisconnected]) { return YES; } if (userId == nil || pass == nil) { return NO; } //設定使用者 [xmppStream setMyJID:[XMPPJID jidWithString:userId]]; //設定伺服器 [xmppStream setHostName:server]; //密碼 password = pass; //串連伺服器 NSError *error = nil; if (![xmppStream connect:&error]) { NSLog(@"cant connect %@", server); return NO; } return YES;}-(void)disconnect{ [self goOffline]; [xmppStream disconnect]; }
這幾個是基礎方法,接下來就是XMPPStreamDelegate中的方法,也是接受好友狀態,接受訊息的重要方法
//串連伺服器- (void)xmppStreamDidConnect:(XMPPStream *)sender{ isOpen = YES; NSError *error = nil; //驗證密碼 [[self xmppStream] authenticateWithPassword:password error:&error]; }//驗證通過- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender{ [self goOnline];}//收到訊息- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{ // NSLog(@"message = %@", message); NSString *msg = [[message elementForName:@"body"] stringValue]; NSString *from = [[message attributeForName:@"from"] stringValue]; NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:msg forKey:@"msg"]; [dict setObject:from forKey:@"sender"]; //訊息委託(這個後面講) [messageDelegate newMessageReceived:dict]; }//收到好友狀態- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence{ // NSLog(@"presence = %@", presence); //取得好友狀態 NSString *presenceType = [presence type]; //online/offline //目前使用者 NSString *userId = [[sender myJID] user]; //線上使用者 NSString *presenceFromUser = [[presence from] user]; if (![presenceFromUser isEqualToString:userId]) { //線上狀態 if ([presenceType isEqualToString:@"available"]) { //使用者列表委託(後面講) [chatDelegate newBuddyOnline:[NSString stringWithFormat:@"%@@%@", presenceFromUser, @"nqc1338a"]]; }else if ([presenceType isEqualToString:@"unavailable"]) { //使用者列表委託(後面講) [chatDelegate buddyWentOffline:[NSString stringWithFormat:@"%@@%@", presenceFromUser, @"nqc1338a"]]; } }}
這裡面有兩個委託方法,一個是使用者列表委託,還有一個就是訊息委託,使用者列表委託主要就是取得線上使用者,更新使用者TableView,訊息委託就是取得好友發送的訊息,並更新訊息TableView,當然這兩個TableView是在不同的Controller中的
定義完兩個委託,我們就要在不同的Controller中實現這兩個委託了
在好友Controller中實現<KKChatDelegate>並寫入如下方法
//取得當前程式的委託-(KKAppDelegate *)appDelegate{ return (KKAppDelegate *)[[UIApplication sharedApplication] delegate]; }//取得當前的XMPPStream-(XMPPStream *)xmppStream{ return [[self appDelegate] xmppStream];}//線上好友-(void)newBuddyOnline:(NSString *)buddyName{ if (![onlineUsers containsObject:buddyName]) { [onlineUsers addObject:buddyName]; [self.tView reloadData]; } }//好友下線-(void)buddyWentOffline:(NSString *)buddyName{ [onlineUsers removeObject:buddyName]; [self.tView reloadData]; }
在viewDidLoad中加入
//設定線上使用者委託 KKAppDelegate *del = [self appDelegate]; del.chatDelegate = self;
這兩行代碼,讓好友名單的委託實現方法在本程式中
在viewWillAppear中加入
[super viewWillAppear:animated]; NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:@"userId"]; if (login) { if ([[self appDelegate] connect]) { NSLog(@"show buddy list"); } }else { //設定使用者 [self Account:self]; }
判斷本地儲存的資料中是否有userId,沒有的話就跳轉到登入頁面
這裡最重要的就是connect了,這一句話就是登入了,成功的話,頁面就會顯示好友名單了。
#pragma mark UITableViewDelegate-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ //start a Chat chatUserName = (NSString *)[onlineUsers objectAtIndex:indexPath.row]; [self performSegueWithIdentifier:@"chat" sender:self]; }-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if ([segue.identifier isEqualToString:@"chat"]) { KKChatController *chatController = segue.destinationViewController; chatController.chatWithUser = chatUserName; }}
當顯示出好友名單,我們選擇一個好友進行聊天
將當前好友名稱發送給聊天頁面
下面是聊天Controller了
在KKChatController.h中加入
NSMutableArray *messages;
這是我們要顯示的訊息,每一條訊息為一條字典
接下來就是每一條訊息的顯示了
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *identifier = @"msgCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]; } NSMutableDictionary *dict = [messages objectAtIndex:indexPath.row]; cell.textLabel.text = [dict objectForKey:@"msg"]; cell.detailTextLabel.text = [dict objectForKey:@"sender"]; cell.accessoryType = UITableViewCellAccessoryNone; return cell; }
跟上面好友Controller一樣,這裡我們也需要XMPPStream
-(KKAppDelegate *)appDelegate{ return (KKAppDelegate *)[[UIApplication sharedApplication] delegate];}-(XMPPStream *)xmppStream{ return [[self appDelegate] xmppStream];}
在ViewDidLoad中加入
KKAppDelegate *del = [self appDelegate];del.messageDelegate = self;
設定訊息委託由自己來接收和處理
#pragma mark KKMessageDelegate-(void)newMessageReceived:(NSDictionary *)messageCotent{ [messages addObject:messageCotent]; [self.tView reloadData]; }
接下來最重要的就是發送訊息了
- (IBAction)sendButton:(id)sender { //本地輸入框中的資訊 NSString *message = self.messageTextField.text; if (message.length > 0) { //XMPPFramework主要是通過KissXML來產生XML檔案 //產生<body>文檔 NSXMLElement *body = [NSXMLElement elementWithName:@"body"]; [body setStringValue:message]; //產生XML訊息文檔 NSXMLElement *mes = [NSXMLElement elementWithName:@"message"]; //訊息類型 [mes addAttributeWithName:@"type" stringValue:@"chat"]; //發送給誰 [mes addAttributeWithName:@"to" stringValue:chatWithUser]; //由誰發送 [mes addAttributeWithName:@"from" stringValue:[[NSUserDefaults standardUserDefaults] stringForKey:USERID]]; //組合 [mes addChild:body]; //發送訊息 [[self xmppStream] sendElement:mes]; self.messageTextField.text = @""; [self.messageTextField resignFirstResponder]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [dictionary setObject:message forKey:@"msg"]; [dictionary setObject:@"you" forKey:@"sender"]; [messages addObject:dictionary]; //重新重新整理tableView [self.tView reloadData]; } }
上面都加了注釋,大家應該能明白,接下來還有一個章節,我們會對發送的訊息在介面進行美化,跟蘋果內建的訊息一樣。謝謝大家有耐心看完,我這個人比較不喜歡打字,所以有的地方注釋比較少,希望大家別介意,還有希望大家能夠多多支援, 以後會接著介紹XMPP檔案傳輸之類的內容。