iOS學習43即時通訊之XMPP(2),iosxmpp

來源:互聯網
上載者:User

iOS學習43即時通訊之XMPP(2),iosxmpp

本篇是 即時通訊之XMPP(2) 接上次 即時通訊之XMPP(1)

1. 好友名單 1> 初始化好友花名冊
    // 擷取管理好友的單例對象    XMPPRosterCoreDataStorage *rosterStorage = [XMPPRosterCoreDataStorage sharedInstance];    // 給roster屬性進行初始化    self.xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:rosterStorage dispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)];    // 將好友名單在通道中啟用    [self.xmppRoster activate:self.xmppStream];    // 設定花名冊代理    [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
 2> XMPPRoster代理方法

  代碼:

#pragma mark - XMPPRosterDelegate代理方法/// 開始擷取好友- (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender{    NSLog(@"開始擷取好友");}/// 結束擷取好友- (void)xmppRosterDidEndPopulating:(XMPPRoster *)sender{    // 當前頁面適用於顯示好友名單的,所以在結束好友擷取的代理方法中要進行重新整理頁面,然後將資料顯示    // 重新整理頁面    [self.tableView reloadData];}// 接收好友的資訊// 這個代理方法會被執行多次,每添加完好友,相對應的好友資訊都要有反饋- (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item{    /*     both 互為好友     none 互不為好友     to 我已經添加對方為好友,但是對方還沒有接受     from 對方已經添加我為好友,但是我還沒有接受     remove 曾經刪除的好友     */        // 描述自己和對方之間的關係    NSString *description = [[item attributeForName:@"subscription"] stringValue];        NSLog(@"description = %@", description);        if ([description isEqualToString:@"to"] || [description isEqualToString:@"none"] || [description isEqualToString:@"both"] || [description isEqualToString:@"from"]) {                // 添加好友        // 擷取添加好友的JID        NSString *friendJID = [[item attributeForName:@"jid"] stringValue];                XMPPJID *jid = [XMPPJID jidWithString:friendJID];                // 如果數組中有這個使用者,就不用再進行操作        if ([self.allRosterArray containsObject:jid]) {            return;        }                // 添加好友到數組        [self.allRosterArray addObject:jid];                // 在tableView中添加這條資料        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.allRosterArray.count - 1 inSection:0];                [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];    }}// 收到好友的監聽請求(加好友請求),是否同意- (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence{    self.fromJID = presence.from;    // 需要相關的提醒框去確定是否接受    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"好友請求" message:@"是否接受好友請求" preferredStyle:UIAlertControllerStyleAlert];        __weak typeof(self)weakSelf = self;        UIAlertAction *acceptAction = [UIAlertAction actionWithTitle:@"接受" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {                // 在花名冊中去接受相關的好友        [[XMPPManager shareXMPPManager].xmppRoster acceptPresenceSubscriptionRequestFrom:weakSelf.fromJID andAddToRoster:YES];    }];        UIAlertAction *rejectAction = [UIAlertAction actionWithTitle:@"拒絕" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {                [[XMPPManager shareXMPPManager].xmppRoster rejectPresenceSubscriptionRequestFrom:weakSelf.fromJID];    }];        [alertController addAction:acceptAction];    [alertController addAction:rejectAction];        [self presentViewController:alertController animated:YES completion:nil];}
 3> 添加好友所需方法

  代碼:

 

- (void)addFriend{    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"添加好友" message:@"請輸入添加好友的名字" preferredStyle:UIAlertControllerStyleAlert];     __weak typeof(self)mySlef = self;        [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {        mySlef.textField = textField;    }];        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {        NSLog(@"取消移除朋友!");    }];        UIAlertAction *ensureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {                // 使用JID記錄        XMPPJID *friendJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@", mySlef.textField.text, kDomin]];        // 監聽好友的動作        [mySlef.xmppRoster subscribePresenceToUser:friendJID];        // 添加好友        [mySlef.xmppRoster addUser:friendJID withNickname:mySlef.textField.text];            }];        [alertController addAction:ensureAction];    [alertController addAction:cancelAction];        [[self getCurrentVC] presentViewController:alertController animated:YES completion:nil];}
4> 移除朋友

代碼:

#pragma mark - 移除朋友- (void)removeFriendWithName:(NSString *)name{    // 使用JID記錄    XMPPJID *friendJID = [XMPPJID jidWithUser:name domain:kDomin resource:kResource];        // 停止監聽好友    [self.xmppRoster unsubscribePresenceFromUser:friendJID];        // 移除朋友    [self.xmppRoster removeUser:friendJID];}
2. 聊天 1> 聊天的規則:
  • 從伺服器擷取聊天記錄,根據資料屬性判斷訊息類型

  • 發送訊息

  • 接收訊息

 2> 初始化訊息歸檔
    // 擷取管理訊息的儲存物件    XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance];    // 訊息管理器的初始化    self.messageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:storage dispatchQueue:dispatch_get_main_queue()];    // 啟用通道    [self.messageArchiving activate:self.xmppStream];    // 設定代理    [self.messageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()];    // 設定訊息管理上下文    self.context = [storage mainThreadManagedObjectContext];
 3> 擷取聊天記錄

  擷取聊天記錄使用CoreData的方式

  • 建立請求

  • 建立實體描述,實體名:   XMPPMessageArchiving_Message_CoreDataObject

  • 建立謂詞查詢條件,條件:streamBareJidStr == 本人Jid AND bareJidStr == 好友Jid

  • 建立排序對象,排序條件:timestamp

  • 執行請求

  代碼:

#pragma mark - 顯示訊息- (void)showMessage{    // 擷取管理上下文    NSManagedObjectContext *contxt = [XMPPManager shareXMPPManager].context;        // 初始化請求對象    NSFetchRequest *request = [NSFetchRequest new];        // 擷取實體    NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:contxt];        // 設定查詢請求的實體    [request setEntity:entity];        // 設定謂詞查詢    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"streamBareJidStr == %@ AND bareJidStr == %@", [XMPPManager shareXMPPManager].xmppStream.myJID.bare, self.chatToJID.bare];    [request setPredicate:predicate];        // 按照時間順序排序    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:YES];    [request setSortDescriptors:@[sort]];        // 執行相關的操作    NSArray *resultArray = [contxt executeFetchRequest:request error:nil];        // 先清空訊息數組    [self.allMessageArray removeAllObjects];        // 添加context執行結果數組    [self.allMessageArray addObjectsFromArray:resultArray];        // 重新整理UI    [self.tableView reloadData];        // 當前聊天記錄跳到最後一行    if (self.allMessageArray.count > 0) {        NSIndexPath * indexPath = [NSIndexPath indexPathForRow:self.allMessageArray.count-1 inSection:0];        // 跳到最後一行        [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom];    }}
 4> 發送訊息
#pragma mark - 發送點擊方法- (void)sendMessageAction{    // 設定message的body    XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJID];        // 發送的內容,一般是從輸入框擷取,這裡我們就寫成固定的值    [message addBody:@"可以"];        // 通過通道進行訊息發送    [[XMPPManager shareXMPPManager].xmppStream sendElement:message];}
 5> 接收/發送訊息的回調

  代碼:

#pragma mark 發送訊息成功- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{    // 重新顯示相關訊息    [self showMessage];}#pragma mark 接受訊息成功- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{    [self showMessage];}#pragma mark 發送訊息失敗- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error{    NSLog(@"發送訊息失敗");}
 6> 訊息氣泡

   代碼:

//重寫message方法,在cell上顯示聊天記錄- (void)setMessage:(NSString *)message{    if (_message != message) {        _message = message;        self.contentLabel.text = _message;        //        self.contentLabel.numberOfLines = 0;        [self.contentLabel sizeToFit];                CGRect rect = self.frame;        if (self.isOut) {//發出去的            self.backgroundImageView.image = [[UIImage imageNamed:@"chat_to"] stretchableImageWithLeftCapWidth:45 topCapHeight:40];            self.backgroundImageView.frame = CGRectMake(rect.size.width - self.contentLabel.frame.size.width - 50-20, 10, self.contentLabel.frame.size.width+20, rect.size.height-20);        }else{//接收的            self.backgroundImageView.image = [[UIImage imageNamed:@"chat_from"] stretchableImageWithLeftCapWidth:45 topCapHeight:40];            self.backgroundImageView.frame = CGRectMake(50, 10,self.contentLabel.frame.size.width+40, rect.size.height-20);        }        //因為contentLabel已經自適應文字大小,故不用設定寬高,但需要設定位置        self.contentLabel.center = CGPointMake(self.backgroundImageView.frame.size.width/2.0, self.backgroundImageView.frame.size.height/2.0);            }}

 

以上代碼均為練習代碼的部分代碼!完整練習代碼github: https://github.com/AlonerOwl/UISenior11_-_1

由於只是練習代碼,對於介面和部分功能沒有最佳化,看起來比較low,如果有需求,請自己進行最佳化。

代碼:

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.