首先是配置XMPP环境,然后建立一个工程,需要建立Core Data的项目,要引入三个框架,如下图,因为用到的XMPPFramework第三方框架中用到了XML解析,所以还要在设置中设置Header Search Paths为/usr/include/libxml2,Other Linker Flags改为-lxml2
XMPPManger.h
1 #import <Foundation/Foundation.h> 2 #import "XMPPFramework.h" // 引入 3 4 @interface XMPPManger : NSObject 5 6 /** 7 * 声明一个通道的属性 8 */ 9 @property (nonatomic, strong) XMPPStream *xmppStream; 10 11 // 创建单例 12 + (instancetype)shareMangaged; 13 14 // 登录的方法 15 - (void)loginWithUserName:(NSString *)userName password:(NSString *)password; 16 17 // 注册的方法 18 - (void)registerWithUserName:(NSString *)userName password:(NSString *)password; 19 20 @end
XMPPManger.m
1 #import "XMPPManger.h" 2 3 // 列举枚举(登录和注册) 4 typedef NS_ENUM(NSUInteger, ConnectToServerPurpose) { 5 ConnectToServerPurposeLogin, 6 ConnectToServerPurposeRegister, 7 }; 8 9 10 @interface XMPPManger () <XMPPStreamDelegate> 11 12 // 登录的属性 13 @property (nonatomic, strong) NSString *userName; // 用户名 14 @property (nonatomic, strong) NSString *password; // 密码 15 16 // 注册的属性 17 @property (nonatomic, strong) NSString *registerUserName; // 用户名 18 @property (nonatomic, strong) NSString *registerPassword; // 密码 19 20 // 记录当前是登录还是注册 21 @property (nonatomic) ConnectToServerPurpose connectToserver; 22 23 @end 24 25 26 static XMPPManger *xmpp = nil; 27 28 @implementation XMPPManger 29 30 // 实现创建单例 31 + (instancetype)shareMangaged { 32 33 static dispatch_once_t onceToken; 34 dispatch_once(&onceToken, ^{ 35 xmpp = [[XMPPManger alloc] init]; 36 }); 37 return xmpp; 38 } 39 40 41 #pragma mark - 创建通道 42 - (instancetype)init { 43 44 if (self = [super init]) { 45 46 // 初始化通道对象 47 self.xmppStream = [[XMPPStream alloc] init]; 48 49 // 设置openfire服务器地址 50 self.xmppStream.hostName = kHostName; 51 52 // 设置服务器端口号 53 self.xmppStream.hostPort = kHostPort; 54 55 // 添加代理 56 [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; 57 } 58 return self; 59 } 60 61 62 #pragma mark - 登录和注册的方法 63 // 登录的方法实现 64 - (void)loginWithUserName:(NSString *)userName password:(NSString *)password { 65 66 self.userName = userName; 67 self.password = password; 68 69 // 记录登录状态 70 self.connectToserver = ConnectToServerPurposeLogin; 71 72 // 链接服务器 73 [self linkServer]; 74 } 75 76 // 注册的方法实现 77 - (void)registerWithUserName:(NSString *)userName password:(NSString *)password { 78 79 self.registerUserName = userName; 80 self.registerPassword = password; 81 82 // 记录登录状态 83 self.connectToserver = ConnectToServerPurposeRegister; 84 85 // 链接服务器 86 [self linkServer]; 87 } 88 89 90 #pragma mark - 链接服务器 91 - (void)linkServer { 92 93 NSString *string = [[NSString alloc] init]; 94 // 区分具体是登录还是注册 95 switch (self.connectToserver) { 96 case ConnectToServerPurposeLogin: 97 string = [NSString stringWithFormat:@"%@", self.userName]; 98 break; 99 case ConnectToServerPurposeRegister: 100 string = [NSString stringWithFormat:@"%@", self.registerUserName]; 101 break; 102 103 default: 104 break; 105 } 106 107 // 要链接服务器,要有用户什么认证 108 // 身份证 109 // 参数1:用户名 110 // 参数2:域名 111 // 参数3:资源 112 XMPPJID *jid = [XMPPJID jidWithUser:string domain:kDomin resource:kResource]; 113 114 // 通过通道进行身份验证 115 self.xmppStream.myJID = jid; 116 117 118 // 如果当前聊天工具处于链接状态或者已经链接了,此时,你需要去切断链接,【此逻辑不唯一】 119 if ([self.xmppStream isConnected] || [self.xmppStream isConnecting]) { 120 [self disconnectToServer]; 121 } 122 123 // 链接超时 124 NSError *error = nil; 125 [self.xmppStream connectWithTimeout:5 error:&error]; 126 127 if (error) { 128 NSLog(@"服务器链接超时"); 129 } 130 } 131 132 133 // 断开链接 134 - (void)disconnectToServer { 135 136 // 当前用户下线了 137 XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"]; 138 139 // 告诉通道下线了 140 [self.xmppStream sendElement:presence]; 141 142 // 使通道失去链接 143 [self.xmppStream disconnect]; 144 } 145 146 147 #pragma mark - XMPPStreamDelegate协议方法 148 #pragma mark - 链接超时 149 - (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender { 150 151 NSLog(@"链接超时"); 152 } 153 154 155 #pragma mark - 链接成功 156 - (void)xmppStreamDidConnect:(XMPPStream *)sender { 157 158 NSLog(@"链接成功"); 159 160 // 区分登录和注册进行密码验证 161 switch (self.connectToserver) { 162 case ConnectToServerPurposeLogin: 163 // 登录密码的验证 164 [self.xmppStream authenticateWithPassword:self.password error:nil]; 165 break; 166 167 case ConnectToServerPurposeRegister: 168 // 注册密码的验证 169 [self.xmppStream registerWithPassword:self.registerPassword error:nil]; 170 break; 171 default: 172 break; 173 } 174 } 175 176 177 #pragma mark - 断开链接 178 - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error { 179 180 // 1.自己手动断开 181 182 // 2.被动断开 183 184 if (error) { 185 NSLog(@"断开链接,error = %@", error); 186 } 187 } 188 189 190 #pragma mark - 认证失败(登录失败) 191 - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error { 192 193 NSLog(@"认证失败, error = %@", error); 194 } 195 196 197 #pragma mark - 认证成功(登录成功) 198 - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender { 199 200 // 上线 201 XMPPPresence *presennce = [XMPPPresence presenceWithType:@"available"]; 202 [self.xmppStream sendElement:presennce]; 203 204 NSLog(@"登录成功"); 205 } 206 207 @end
LoginViewcontroller.m(登录)
1 #import "LoginViewcontroller.h" 2 #import "XMPPManger.h" 3 4 @interface LoginViewcontroller () 5 6 @property (weak, nonatomic) IBOutlet UITextField *nameLabel; 7 @property (weak, nonatomic) IBOutlet UITextField *passwordLabel; 8 9 @end 10 11 @implementation LoginViewcontroller 12 13 - (void)viewDidLoad { 14 [super viewDidLoad]; 15 // Do any additional setup after loading the view. 16 } 17 18 19 // 登录按钮点击事件 20 - (IBAction)loginAction:(UIButton *)sender { 21 22 [[XMPPManger shareMangaged] loginWithUserName:self.nameLabel.text password:self.passwordLabel.text]; 23 } 24 25 @end
RegisterViewController.m(注册)
因为我们使用的是模态推出,所以我们点击注册按钮的同时需要返回到上一页,因此,注册所用的一些方法我们可以放在此文件中写,都在XMPPManger.m中也可以
1 #import "RegisterViewController.h" 2 #import "XMPPManger.h" 3 4 @interface RegisterViewController () <XMPPStreamDelegate> 5 6 @property (weak, nonatomic) IBOutlet UITextField *nameTextField; 7 @property (weak, nonatomic) IBOutlet UITextField *passwordTextfield; 8 9 @end 10 11 @implementation RegisterViewController 12 13 - (void)viewDidLoad { 14 [super viewDidLoad]; 15 // Do any additional setup after loading the view. 16 17 [[XMPPManger shareMangaged].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; 18 } 19 20 21 // 注册的方法 22 - (IBAction)registerAction:(UIButton *)sender { 23 24 [[XMPPManger shareMangaged] registerWithUserName:self.nameTextField.text password:self.passwordTextfield.text]; 25 } 26 27 28 #pragma mark - XMPPStreamDelegate实现协议方法 29 // 实现协议是为了实现需求:注册成功之后dismiss到登录界面 30 // 注册成功 31 - (void)xmppStreamDidRegister:(XMPPStream *)sender { 32 33 NSLog(@"注册成功"); 34 35 [self dismissViewControllerAnimated:YES completion:^{ 36 37 }]; 38 } 39 40 41 // 注册失败 42 - (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error { 43 44 NSLog(@"注册失败 = %@", error); 45 } 46 47 @end