iOS讲解迷惑--XMPP进阶 添加好友, 与好友聊天 (包括登录注册)

单例

//
//  XMPPManager.m
//  XMPP_BJS150727
//
//  Created by  on 15/10/20.
//  Copyright (c) 2015年 nyl. All rights reserved.
//

#import "XMPPManager.h"

typedef NS_ENUM(NSUInteger, ConnectToServerPurpose) {
    ConnectToServerPurposeLogin,
    ConnectToServerPurposeRegister,
};

@interface XMPPManager ()<XMPPStreamDelegate, XMPPRosterDelegate, UIAlertViewDelegate>

@property (nonatomic) ConnectToServerPurpose connectToServerPurpose;


// 登录密码
@property (nonatomic, strong) NSString *loginPassword;

// 注册密码
@property (nonatomic, strong) NSString *registerPassword;


@end

@implementation XMPPManager

+ (XMPPManager *)defaultManager
{
    static XMPPManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[XMPPManager alloc] init];
    });
    return manager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        // 初始化通道
        self.xmppStream = [[XMPPStream alloc] init];
        // 设置域名
        self.xmppStream.hostName = kHostName;
        self.xmppStream.hostPort = kHostPort;
        // 添加代理
        [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
        
        
        
        // 初始化花名册
        XMPPRosterCoreDataStorage *xmppRosterStorage = [XMPPRosterCoreDataStorage sharedInstance];
        self.xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage dispatchQueue:dispatch_get_main_queue()];
        // 添加代理
        [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
        // 好友花名册在通道上激活,相当于授权
        [self.xmppRoster activate:self.xmppStream];
        
        
        
        // 这里是聊天界面用的
        // 初始化消息归档
        XMPPMessageArchivingCoreDataStorage *messageArchivingCoreDataStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
        self.xmppMessageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:messageArchivingCoreDataStorage dispatchQueue:dispatch_get_main_queue()];
        // 激活
        [self.xmppMessageArchiving activate:self.xmppStream];
        
        self.messageContext = messageArchivingCoreDataStorage.mainThreadManagedObjectContext;
        
    }
    return self;
}


#pragma mark - 登录
- (void)loginWithUserNameString:(NSString *)userName password:(NSString *)password
{
    // 记录登录密码
    self.loginPassword = password;
    // 建立在连接的基础上执行登录
    [self connectToServerWithUserName:userName];
    self.connectToServerPurpose = ConnectToServerPurposeLogin;
    
}
#pragma mark - 注册
- (void)registerWithUserNameString:(NSString *)userName password:(NSString *)password
{
    // 记录登录密码
    self.registerPassword = password;
    // 建立在连接的基础上执行注册
    [self connectToServerWithUserName:userName];
    self.connectToServerPurpose = ConnectToServerPurposeRegister;
}


// 设置连接请求的身份
- (void)connectToServerWithUserName:(NSString *)userName
{
    // 设置连接请求的身份, 相当于身份证
    XMPPJID *myJid = [XMPPJID jidWithUser:userName domain:kDomin resource:kResource];
    self.xmppStream.myJID = myJid;
    [self connectToServer];
}

// 连接
- (void)connectToServer
{
    if ([self.xmppStream isConnected] || [self.xmppStream isConnecting]) {
        // 如果通道已经连接或者正在连接中,断开连接,执行新的连接
        [self disConnect]; // 断开连接
    }
    NSError *error;
    
    // 进行与服务器的连接
    [self.xmppStream connectWithTimeout:30 error:&error];
    if (error) {
        NSLog(@"连接失败");
    }
}

// 断开连接 (断开连接的前要保证用户下线)
- (void)disConnect
{
    // 如果断开了连接,要保证用户下线
    // 1.生成下线状态
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    // 2.将元素插入XML文件
    [self.xmppStream sendElement:presence];
    // 断开与服务器连接
    [self.xmppStream disconnect];
}

#pragma mark - XMPPStreamDelegate

// 连接超时
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
{
    NSLog(@"连接超时 %s,%d", __FUNCTION__ , __LINE__);
}
// 连接成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
    NSLog(@"连接成功 %s,%d", __FUNCTION__ , __LINE__);
    
    switch (self.connectToServerPurpose) {
        case ConnectToServerPurposeLogin:
            // 连接成功,登录
            [self.xmppStream authenticateWithPassword:self.loginPassword error:nil];
            break;
        case ConnectToServerPurposeRegister:
            // 连接成功,注册
            [self.xmppStream registerWithPassword:self.registerPassword error:nil];
            break;
        default:
            break;
    }
}
// 断开连接成功
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
    NSLog(@"断开连接成功 %s,%d", __FUNCTION__ , __LINE__);
}

// 未登录
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
    NSLog(@"未登录 %s,%d", __FUNCTION__ , __LINE__);
}



/**
 *  在连接成功的代理方法里面 生成上线状态
 */
// 已登录
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    NSLog(@"已登录 %s,%d", __FUNCTION__ , __LINE__);
    // Authenticate ---认证
    // 在通道设置上线状态
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
    [self.xmppStream sendElement:presence];
    
}

// 注册成功
- (void)xmppStreamDidRegister:(XMPPStream *)sender
{
    NSLog(@"注册成功%s,%d", __FUNCTION__ , __LINE__);
    
}
// 注册失败
- (void)xmppStream:sender didNotRegister:(DDXMLElement *)error
{
    NSLog(@"注册失败 %s,%d", __FUNCTION__ , __LINE__);
}









#pragma mark - 添加好友
- (void)addNewFriend
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"添加好友" message:@"输入好友名称" delegate:self cancelButtonTitle:@"add" otherButtonTitles:nil];
    alert.alertViewStyle = UIAlertViewStylePlainTextInput;
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
        {
            NSLog(@"%@", alertView);
            UITextField *textField = [alertView textFieldAtIndex:0];
            // 生成好友jid
            XMPPJID *jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@", textField.text, kDomin]];
            
            // 第 1 种方法: 添加好友, 其对应的删除好友方法是, [self.xmppRoster unsubscribePresenceFromUser:jid];
            //[self.xmppRoster subscribePresenceToUser:jid]; // 添加好友
            
            
            // 第 2 种方法: 添加好友,其对应的删除好友方法是, [self.xmppRoster removeUser:jid];
            [self.xmppRoster addUser:jid withNickname:@"nickname"];//添加好友
            break;
        }
        default:
            break;
    }
}



#pragma mark - 退出登录
- (void)exitLogin
{
    // 断开连接
    [self disConnect];
}




#pragma mark - 删除好友
- (void)removeFriendWithUserName:(NSString *)userName
{
    XMPPJID *jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@", userName, kDomin]];
    // 删除好友
    [self.xmppRoster removeUser:jid];
    
}

@end


登录VC

//
//  LoginViewController.m

//
//  Created by on 15/10/20.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "LoginViewController.h"
#import "XMPPManager.h"


@interface LoginViewController ()

@property (strong, nonatomic) IBOutlet UITextField *userNameText;
@property (strong, nonatomic) IBOutlet UITextField *passwordText;


@property (nonatomic, assign) BOOL isAutoLogin;

@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)actionIsAutoLogin:(id)sender {
    
    UIButton *button = sender;
    _isAutoLogin = !_isAutoLogin;
    if (_isAutoLogin) {
        // 自动登录
        [button setImage:[UIImage imageNamed:@"yes_image"] forState:UIControlStateNormal];
    } else {
        // 不自动登录
        [button setImage:[UIImage imageNamed:@"no_image"] forState:UIControlStateNormal];
    }
}




// 登录按钮点击事件
- (IBAction)loginMySelf:(id)sender {
    [[XMPPManager defaultManager] loginWithUserNameString:self.userNameText.text password:self.passwordText.text];
}


// 未登录
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
    NSLog(@"未登录 %s,%d", __FUNCTION__ , __LINE__);
}
// 已登录
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    NSLog(@"已登录 %s,%d", __FUNCTION__ , __LINE__);
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    if (_isAutoLogin) {
        // 自动登录
        [userDefaults setObject:self.userNameText.text forKey:@"userName"];
        [userDefaults setObject:self.passwordText.text forKey:@"password"];
        [userDefaults setObject:[NSNumber numberWithBool:self.isAutoLogin]forKey:@"isAutoLogin"];
    } else {
        // 不自动登录
        [userDefaults setObject:[NSNumber numberWithBool:self.isAutoLogin]forKey:@"isAutoLogin"];
    }
    // 同步数据
    [userDefaults synchronize];
    
    [self dismissViewControllerAnimated:YES completion:nil];
}




- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


注册VC

//
//  RegisterViewController.m

//
on 15/10/20.
//  Copyright (c) 2015年 All rights reserved.
//

#import "RegisterViewController.h"
#import "XMPPManager.h"

@interface RegisterViewController ()

@property (strong, nonatomic) IBOutlet UITextField *userNameText;

@property (strong, nonatomic) IBOutlet UITextField *passwordText;


@end

@implementation RegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
}

- (IBAction)registerMyAction:(id)sender {
    [[XMPPManager defaultManager] registerWithUserNameString:self.userNameText.text password:self.passwordText.text];
    
}

// 注册成功
- (void)xmppStreamDidRegister:(XMPPStream *)sender
{
    NSLog(@"注册成功%s,%d", __FUNCTION__ , __LINE__);
    [[XMPPManager defaultManager] loginWithUserNameString:self.userNameText.text password:self.passwordText.text];
}
// 注册失败
- (void)xmppStream:sender didNotRegister:(DDXMLElement *)error
{
    NSLog(@"注册失败 %s,%d", __FUNCTION__ , __LINE__);
}
// 未登录
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
    NSLog(@"未登录 %s,%d", __FUNCTION__ , __LINE__);
}       
// 已登录
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    NSLog(@"已登录 %s,%d", __FUNCTION__ , __LINE__);
    
    [self dismissViewControllerAnimated:YES completion:nil];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


好友列表VC (花名册)

//
//  FriendTableViewController.m

//
//  Created by l on 15/10/21.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "FriendTableViewController.h"
#import "ChatTableViewController.h"
#import "LoginViewController.h"

@interface FriendTableViewController ()<XMPPRosterDelegate, UIAlertViewDelegate>

@property (nonatomic, strong) NSMutableArray *rosterArray;

@property (nonatomic, strong) XMPPJID *friendJid; // 获取到的好友请求的jid


@end

@implementation FriendTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[XMPPManager defaultManager].xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
}

#pragma mark - 退出登录

- (IBAction)actionExitLogin:(id)sender {

    // 断开连接,用户下线
    [[XMPPManager defaultManager] exitLogin];
    
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:[NSNumber numberWithBool:NO]forKey:@"isAutoLogin"];
    
    // 弹出登录页面
    // 找到登录注册的SB文件1
    UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"LoginAndRegister" bundle:nil];
    
    // 得到箭头指向的VC
    UIViewController *loginVC = [storyBoard instantiateInitialViewController];
    [self presentViewController:loginVC animated:YES completion:nil];
}



- (IBAction)addFriend:(id)sender {
    [[XMPPManager defaultManager] addNewFriend];
}

#pragma mark - XMPPRoserDelegate

- (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender
{
    NSLog(@"开始获取好友 %s,%d", __FUNCTION__ , __LINE__);
}

- (void)xmppRosterDidEndPopulating:(XMPPRoster *)sender
{
    NSLog(@"停止获取好友  %s,%d", __FUNCTION__ , __LINE__);
}

- (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item
{
    // 获取一个好友走一次这个方法
    NSLog(@"获取的好友 %s,%d", __FUNCTION__ , __LINE__);
    NSLog(@"friend ===== %@", item);
    
    // none:互相没有订阅
    // to:你订阅了别人,他同意了,但是他并没有订阅你
    // from:你被他订阅了,但你没有订阅他
    // both:互粉
    // remove:删除好友
    
    // 只显示互粉的情况
    NSString *sub = [[item attributeForName:@"subscription"] stringValue];
    if (![sub isEqualToString:@"both"]) {
        return;
    }
    
    // 把XML中的元素转化成字符串
    NSString *jidString = [[item attributeForName:@"jid"] stringValue];
    XMPPJID *jid = [XMPPJID jidWithString:jidString resource:kResource];
    
    if ([self.rosterArray containsObject:jid]) {
        return;
    }
    // 存储获取的好友
    [self.rosterArray addObject:jid];
    
    // 插入到tableView中
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.rosterArray.count - 1 inSection:0];
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
    
}

#pragma mark - 被动添加好友
// 获取好友请求
- (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence
{
    NSLog(@"接收到好友请求 %s,%d", __FUNCTION__ , __LINE__);
    
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"收到好友请求" message:presence.from.user delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    [alertView show];
    
    // 记录好友请求的jid
    self.friendJid = presence.from;
//    // 可以执行拒绝添加或者同意添加
//    // 拒绝
//    [[XMPPManager defaultManager].xmppRoster rejectPresenceSubscriptionRequestFrom:presence.from];
//    // 同意
//    [[XMPPManager defaultManager].xmppRoster acceptPresenceSubscriptionRequestFrom:presence.from andAddToRoster:YES];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
            // 拒绝
            [[XMPPManager defaultManager].xmppRoster rejectPresenceSubscriptionRequestFrom:self.friendJid];
            break;
        case 1:
            // 同意
            [[XMPPManager defaultManager].xmppRoster acceptPresenceSubscriptionRequestFrom:self.friendJid andAddToRoster:YES];
            break;
        default:
            break;
    }
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.rosterArray.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FriendCell" forIndexPath:indexPath];
    
    // 数据保护
    if (self.rosterArray.count > 0) {
        XMPPJID *jid = [self.rosterArray objectAtIndex:indexPath.row];
        // 显示好友名字
        cell.textLabel.text = jid.user;
        // bare: 好友名字@域名 ( eg:admin@127.0.0.1 )
        NSLog(@"jid == %@", jid.bare);
    }
    return cell;
}



// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}


// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        
        XMPPJID *jid = [self.rosterArray objectAtIndex:indexPath.row];
        [[XMPPManager defaultManager] removeFriendWithUserName:jid.user];
        
        [self.rosterArray removeObjectAtIndex:indexPath.row];
        
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}


/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

- (NSMutableArray *)rosterArray
{
    if (!_rosterArray) {
        _rosterArray = [NSMutableArray array];
    }
    return _rosterArray;
}





#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    
    ChatTableViewController *chatVC = [segue destinationViewController]; // 线指向的VC
    
    // 获取cell
    UITableViewCell *cell = sender; // 线起始点对应的控件
    
    // 得到点击的位置(行)
    NSInteger index = [self.tableView indexPathForCell:cell].row;
    XMPPJID *jid = [self.rosterArray objectAtIndex:index];
    chatVC.chatToString = jid.bare;
    
    
}


@end



聊天VC.h

//
//  ChatTableViewController.h

//  Created by l on 15/10/21.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>
#import "XMPPManager.h"

@interface ChatTableViewController : UITableViewController<XMPPStreamDelegate>


@property (nonatomic, strong) NSString *chatToString; // 好友的bare



@end



聊天VC.m

<span style="font-family: Arial, Helvetica, sans-serif;">//</span>
//  ChatTableViewController.m
//
//  Created byon 15/10/21.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "ChatTableViewController.h"


@interface ChatTableViewController ()

@property (nonatomic, strong) NSMutableArray *messageArray;


@end

@implementation ChatTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
    
    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
    
    [[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];

}

// 发送消息
- (IBAction)sendMessage:(id)sender {
    XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:[XMPPJID jidWithString:self.chatToString resource:kResource]];
    [message addBody:@"大红包!!!!"];
    
    [[XMPPManager defaultManager].xmppStream sendElement:message];
    
}

// 获得消息
- (void)reloadMessage
{
    // 取消息
    NSManagedObjectContext *context = [XMPPManager defaultManager].messageContext;
    // 创建请求对象
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//    XMPPMessageArchiving_Message_CoreDataObject
    // 创建实体描述,用于描述(指定)所查询的实体
    NSEntityDescription *entityDes = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context];
    [fetchRequest setEntity:entityDes];
    
    // 所有的消息都存储在这个实体里,需要取出与当前好友的聊天记录,使用谓词(查询条件)的方式进行限定
    // 查询条件 自己的jid.bare 和好友的jid.bare
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"streamBareJidStr == %@ AND bareJidStr == %@", [XMPPManager defaultManager].xmppStream.myJID.bare, self.chatToString];
    [fetchRequest setPredicate:predicate];
    
    // 排序,根据时间进行排序
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:YES];
    [fetchRequest setSortDescriptors:@[sortDescriptor]];
    
    // 执行查询请求
    NSArray *resultArray = [context executeFetchRequest:fetchRequest error:nil];
    
    if (self.messageArray.count > 0) {
        [self.messageArray removeAllObjects];
    }
    [self.messageArray addObjectsFromArray:resultArray];
    [self.tableView reloadData];
    
    if (self.messageArray.count > 0) {
        // tableView 自动滚动到最新消息行
        NSIndexPath *index = [NSIndexPath indexPathForRow:self.messageArray.count - 1 inSection:0];
        [self.tableView scrollToRowAtIndexPath:index atScrollPosition:(UITableViewScrollPositionTop) animated:YES]; // 滚到指定行
    }
    
}

- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error
{
    NSLog(@"发送消息失败 %s,%d", __FUNCTION__ , __LINE__);
}
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
{
    NSLog(@"发送消息成功 %s,%d", __FUNCTION__ , __LINE__);
    [self reloadMessage];
}

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
    NSLog(@"接收消息 %s,%d", __FUNCTION__ , __LINE__);
    [self reloadMessage];
}






- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.messageArray.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ChatCell" forIndexPath:indexPath];
    
    // Configure the cell...
    if (self.messageArray.count > 0) {
        // 取出数组中的message对象
        XMPPMessageArchiving_Message_CoreDataObject *message = [self.messageArray objectAtIndex:indexPath.row];
        if (message.isOutgoing == YES) {
            // 发出的信息
            cell.textLabel.text = @"";
            cell.detailTextLabel.text = message.body;
        } else {
            // 接收的消息
            cell.textLabel.text = message.body;
            cell.detailTextLabel.text = @"";
        }
    }
    return cell;
}


/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

- (NSMutableArray *)messageArray
{
    if (!_messageArray) {
        _messageArray = [NSMutableArray array];
    }
    return _messageArray;
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


AppDelegate

<pre name="code" class="objc">//
//  AppDelegate.m
//  XMPP_BJS150727
//
//  Created by  on 15/10/20.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "AppDelegate.h"
#import "XMPPManager.h"

@interface AppDelegate ()<XMPPStreamDelegate>

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    // 判断是否是自动登录
    // 取出存在持久化里的状态
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSNumber *autoLogin = [userDefaults objectForKey:@"isAutoLogin"];
    BOOL isAutoLogin = [autoLogin boolValue];
//    NSLog(@"%d",isAutoLogin);
    if (isAutoLogin) {
        NSString *userName = [userDefaults objectForKey:@"userName"];
        NSString *password = [userDefaults objectForKey:@"password"];
        // 添加代理
        [[XMPPManager defaultManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
        [[XMPPManager defaultManager] loginWithUserNameString:userName password:password];
    } else {
#pragma mark - 从main.SB 到 LoginAndRegister.SB
        // 显示视图
        [self.window makeKeyAndVisible];
            // 找到登录注册的SB文件
            UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"LoginAndRegister" bundle:nil];
            // 得到箭头指向的VC
            UIViewController *loginVC = [storyBoard instantiateInitialViewController];
            [self.window.rootViewController presentViewController:loginVC animated:YES completion:nil];
        
        // 下面的方法通过SB中对VC设置的id 获取指定的控制器对象
        // - (id)instantiateViewControllerWithIdentifier:(NSString *)identifier;
    }
    
    return YES;
}

// 未登录
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
    NSLog(@"未登录 %s,%d", __FUNCTION__ , __LINE__);
}
// 已登录
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    NSLog(@"已登录 %s,%d", __FUNCTION__ , __LINE__);
    // 显示视图
    [self.window makeKeyAndVisible];
}


- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值