IOS learning 43 instant messaging XMPP (2), iosxmpp
This article describes how to connect XMPP (2) with Instant Messaging (XMPP) (1)
1. Friends List 1> initialize friends roster
// Obtain the singleton object XMPPRosterCoreDataStorage * rosterStorage = [XMPPRosterCoreDataStorage sharedInstance] for managing friends; // initialize self for the roster attribute. xmppRoster = [[XMPPRoster alloc] initWithRosterStorage: rosterStorage dispatchQueue: dispatch_get_global_queue (Friends, 0)]; // activate [self. xmppRoster activate: self. xmppStream]; // sets the roster proxy [self. xmppRoster addDelegate: self delegateQueue: dispatch_get_main_queue ()];
2> XMPPRoster proxy method
Code:
# Pragma mark-XMPPRosterDelegate proxy method // start to get friends-(void) xmppRosterDidBeginPopulating :( XMPPRoster *) sender {NSLog (@ "start to get friends ");} /// end obtaining friends-(void) xmppRosterDidEndPopulating :( XMPPRoster *) sender {// the current page is applicable to displaying the friends list, therefore, you need to refresh the page in the proxy method obtained by friends, and then display the data // refresh the page [self. tableView reloadData];} // receive friend information // This proxy method is executed multiple times. Each time a friend is added, the corresponding friend information must be fed back-(void) xmppRoster :( XMPPRoster *) sender didReceiveRosterItem :( DDXMLElement *) item {/* both mutual friend none mutual friend to I have already added peer to friend, however, the other party has not accepted the "from" request. The other party has added me as a friend, however, I have not yet accepted the remove deleted friend * // describe the relationship between myself and the other party NSString * description = [[item attributeForName: @ "subcategory"] stringValue]; NSLog (@ "description = % @", description); if ([description isrequired tostring: @ "to"] | [description isrequired tostring: @ "none"] | [description isinclutostring: @ "both"] | [description isinclutostring: @ "from"]) {// Add a friend // obtain the JID NSString * friendJID = [[item attributeForName: @ "jid"] stringValue]; XMPPJID * jid = [XMPPJID jidWithString: friendJID]; // if this user exists in the array, the operation if ([self. allRosterArray containsObject: jid]) {return;} // Add friends to the array [self. allRosterArray addObject: jid]; // Add this data NSIndexPath * indexPath = [NSIndexPath indexPathForItem: self. allRosterArray. count-1 inSection: 0]; [self. tableView insertRowsAtIndexPaths: @ [indexPath] withRowAnimation: UITableViewRowAnimationRight];} // receives a friend's listening request (add friend request), whether to agree-(void) xmppRoster :( XMPPRoster *) sender didReceivePresenceSubscriptionRequest :( XMPPPresence *) presence {self. fromJID = presence. from; // related reminder boxes are required to determine whether to accept UIAlertController * alertController = [UIAlertController alertControllerWithTitle: @ "friend request" message: @ "accept friend request" preferredStyle: accept]; _ weak typeof (self) weakSelf = self; UIAlertAction * acceptAction = [UIAlertAction actionWithTitle: @ "accept" style: UIAlertActionStyleDefault handler: ^ (UIAlertAction * _ Nonnull action) {// accept related friends in the Roster [[XMPPManager shareXMPPManager]. xmppRoster acceptPresenceSubscriptionRequestFrom: weakSelf. fromJID andAddToRoster: YES];}]; UIAlertAction * rejectAction = [UIAlertAction actionWithTitle: @ "reject" 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> methods required to add friends
Code:
-(Void) addFriend {UIAlertController * alertController = [UIAlertController alertControllerWithTitle: @ "add friend" message: @ "enter the name of your friend" preferredStyle: UIAlertControllerStyleAlert] _ weak typeof (self) mySlef = self; [alertController addTextFieldWithConfigurationHandler: ^ (UITextField * _ Nonnull textField) {mySlef. textField = textField;}]; UIAlertAction * cancelAction = [UIAlertAction actionWithTitle: @ "cancel" Style: UIAlertActionStyleCancel handler: ^ (UIAlertAction * _ Nonnull action) {NSLog (@ "cancel friend deletion! ") ;}]; UIAlertAction * ensureAction = [UIAlertAction actionWithTitle: @" OK "style: UIAlertActionStyleDefault handler: ^ (UIAlertAction * _ Nonnull action) {// use JID to record XMPPJID * friendJID = [XMPPJID jidWithString: [NSString stringWithFormat: @ "% @", mySlef. textField. text, kDomin]; // listens for friend actions [mySlef. xmppRoster subscribePresenceToUser: friendJID]; // Add a friend [mySlef. xmppRoster addUser: friendJID withNickname: mySlef. textField. text] ;}]; [alertController addAction: ensureAction]; [alertController addAction: cancelAction]; [[self getCurrentVC] presentViewController: alertController animated: YES completion: nil];}
4> Delete friends
Code:
# Pragma mark-delete friend-(void) removeFriendWithName :( NSString *) name {// use JID to record XMPPJID * friendJID = [XMPPJID jidWithUser: name domain: kDomin resource: kResource]; // stop listening to friends [self. xmppRoster unsubscribePresenceFromUser: friendJID]; // delete a friend [self. xmppRoster removeUser: friendJID];}
2. Chat 1> chat rules:
2> initialize message Archiving
// Obtain the storage object XMPPMessageArchivingCoreDataStorage * storage = [XMPPMessageArchivingCoreDataStorage sharedInstance]; // message manager initialization self. messageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage: storage dispatchQueue: dispatch_get_main_queue ()]; // activate the channel [self. messageArchiving activate: self. xmppStream]; // sets the proxy [self. messageArchiving addDelegate: self delegateQueue: dispatch_get_main_queue ()]; // sets the message management context self. context = [storage mainThreadManagedObjectContext];
3> get chat records
Obtain chat records using CoreData
CREATE request
Create object description, Object Name: XMPPMessageArchiving_Message_CoreDataObject
Create a predicate query condition. condition: streamBareJidStr = My Jid AND bareJidStr = friend Jid
Create a sorting object. The sorting condition is timestamp.
Execute request
Code:
# Pragma mark-Display message-(void) showMessage {// obtain the management context NSManagedObjectContext * contxt = [XMPPManager shareXMPPManager]. context; // initialize the request object NSFetchRequest * request = [NSFetchRequest new]; // obtain the entity NSEntityDescription * entity = [NSEntityDescription entityForName: @ "entity" inManagedObjectContext: contxt]; // set the object of the query request [request setEntity: entity]; // set the predicate query NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "streamBareJidStr ==%@ AND bareJidStr ==%@", [XMPPManager shareXMPPManager]. xmppStream. myJID. bare, self. chatToJID. bare]; [request setPredicate: predicate]; // sort by time. NSSortDescriptor * sort = [[delealloc] initWithKey: @ "timestamp" ascending: YES]; [request setSortDescriptors: @ [sort]; // execute related operations NSArray * resultArray = [contxt executeFetchRequest: request error: nil]; // first clear the message array [self. allMessageArray removeAllObjects]; // Add the context execution result array [self. allMessageArray addObjectsFromArray: resultArray]; // refresh the UI [self. tableView reloadData]; // The current chat record jumps to the last line if (self. allMessageArray. count> 0) {NSIndexPath * indexPath = [NSIndexPath indexPathForRow: self. allMessageArray. count-1 inSection: 0]; // jump to the last line [self. tableView selectRowAtIndexPath: indexPath animated: YES scrollPosition: UITableViewScrollPositionBottom];}
4> send messages
# Pragma mark-sending and clicking method-(void) sendMessageAction {// set the message body XMPPMessage * message = [XMPPMessage messageWithType: @ "chat" to: self. chatToJID]; // The sent content, which is generally obtained from the input box. Here we write a fixed value [message addBody: @ "yes"]; // send messages through the channel [[XMPPManager shareXMPPManager]. xmppStream sendElement: message];}
5> receive/Send message callback
Code:
# Pragma mark message sent successfully-(void) xmppStream :( XMPPStream *) sender didSendMessage :( XMPPMessage *) message {// re-display related message [self showMessage];} # pragma mark received the message successfully-(void) xmppStream :( XMPPStream *) sender didReceiveMessage :( XMPPMessage *) message {[self showMessage] ;}# pragma mark failed to send the message-(void) xmppStream :( XMPPStream *) sender didFailToSendMessage :( XMPPMessage *) message error :( NSError *) error {NSLog (@ "message sending failed ");}
6> message bubbles
Code:
// Rewrite the message method and display the chat record-(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 {// received 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);} // because contentLabel is adaptive to the text size, you do not need to set the width and height, but you need to set the position self. contentLabel. center = CGPointMake (self. backgroundImageView. frame. size. width/2.0, self. backgroundImageView. frame. size. height/2.0 );}}
The above code is part of the exercise code! Complete exercise code github: https://github.com/AlonerOwl/UISenior11_-_1
Because it is just a practice code, the interface and some functions are not optimized and it looks relatively low. If you need it, please optimize it yourself.
Code: