Habber - IOS XMPP 客户端 教程 (二)应用XMPP&代理&全局变量
来源:互联网 发布:word2010 mac 破解版 编辑:程序博客网 时间:2024/06/06 17:10
底层始于XMPP
首先构筑底层,底层为上层服务,也就是我们对XMPP框架提供接口编程的应用。
我是在AppDelegate中写的,可是为什么要在AppDelegate中写?
Nice question! Cuz the demo which the author gave was written in AppDelegate.
好吧,开个玩笑,不过按照我的理解,创建在AppDelegate中原因只是app的生命周期内,我们也只需要创建一个单例,一个xmppStream,然后进行接收传递等数据都靠这同一个流。
事实上完全可以在别的地方写,但是引用起来可能差强人意了,因为还是要引用同一个XMPPStream,怎样获取是个问题。
先看一下AppDelegate.h文件:
//// AppDelegate.h// Habber//// Created by Sunny on 12/15/15.// Copyright © 2015 Nine. All rights reserved.//#import <UIKit/UIKit.h>#import <XMPP.h>#import "Statics.h"#import "HabberMessageDelegate.h"#import "HabberChatDelegate.h"@interface AppDelegate : UIResponder <UIApplicationDelegate, XMPPStreamDelegate> { //是否连接状态 BOOL isOpen;}@property (strong, nonatomic) UIWindow *window;//用于传输xmpp协议数据的封装流。@property (nonatomic, readonly) XMPPStream *xmppStream;//密码@property (nonatomic, strong) NSString *password;@property (nonatomic, strong) id<HabberChatDelegate> chatDelegate;@property (nonatomic, strong) id<HabberMessageDelegate> messageDelegate;//XMPPStream的初始化- (void)setupStream;//连接功能- (BOOL)connect;- (void)disconnect;//控制上下线- (void)goOnline;- (void)goOffline;@end
可以看到它的主要功能就是这些了,继承XMPPStreamDelegate与服务器进行交互,并返回状态,剩下的交给代理(HabberChatDelegate、HabberMessageDelegate)去做。
这里isOpen这个在我给的代码中不用写也可以运行,本来想用来控制服务器是否连接状态的,不过程序中没有用上。但是应该有一个对服务器判断的,减少不必要的开销和消除bug
接下来看看AppDelegate.m中做了什么:
//// AppDelegate.m// Habber//// Created by Sunny on 12/15/15.// Copyright © 2015 Nine. All rights reserved.//#import "AppDelegate.h"@interface AppDelegate ()@property (strong, nonatomic) UIImageView *splashView;@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //设置界面显示等,标题栏颜色,状态栏颜色,字体大小等 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; [[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:36.0/255 green:36.0/255 blue:36.0/255 alpha:0.9]]; [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]]; [[UIBarButtonItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont boldSystemFontOfSize:13], NSFontAttributeName, nil] forState:UIControlStateNormal]; //程序打开自动连接服务器 [self connect]; [NSThread sleepForTimeInterval:1.5]; return YES;}- (void)applicationWillResignActive:(UIApplication *)application {}- (void)applicationDidEnterBackground:(UIApplication *)application {}- (void)applicationWillEnterForeground:(UIApplication *)application {}- (void)applicationDidBecomeActive:(UIApplication *)application {}- (void)applicationWillTerminate:(UIApplication *)application { [self disconnect];}//XMPPStream初始化- (void)setupStream { _xmppStream = [XMPPStream new]; //设置线程// [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)]; //像上面这样,放到其它线程中,那么代理和通知修改界面的时候就会出现问题,至于放到主线程中来,反正它里面集成的多线程操作可以应付消息传递了。 [_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];}//发送连接服务器请求- (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 isConnected]) { return YES; } //没有用户名密码我也不去连接 if (userId == nil || pass == nil) { return NO; } //设置用户 [_xmppStream setMyJID:[XMPPJID jidWithString:userId]]; //密码 _password = pass; //设置服务器 [_xmppStream setHostName:server]; //连接服务器 NSError *error = nil; if (![_xmppStream connectWithTimeout:5.0 error:&error]) { return NO; } [_chatDelegate didConnect]; return YES;}- (void)disconnect { [self goOffline]; [_xmppStream disconnect]; [_chatDelegate didDisconnect];}- (void)acceptFriendRequest {}//控制上下线- (void)goOnline { //发送在线状态 XMPPPresence *presence = [XMPPPresence presence]; [[self xmppStream] sendElement:presence];}- (void)goOffline { //发送下线状态 XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"]; [[self xmppStream] sendElement:presence];}#pragma mark - XMPPStreamDelegate实现- (void)xmppStreamDidConnect:(XMPPStream *)sender { isOpen = YES; NSError *error = nil; //验证密码 [[self xmppStream] authenticateWithPassword:_password error:&error];}- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error { [[NSNotificationCenter defaultCenter] postNotificationName:@"authenticateFail" object:nil];}- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender { [self goOnline]; [[NSNotificationCenter defaultCenter] postNotificationName:@"hasAuthenticated" object:nil];}- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error { isOpen = NO; [[NSNotificationCenter defaultCenter] postNotificationName:@"connectServerFailed" object:nil];}//收到消息后把消息传递给代理- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { //封装好的 文字 + 发送人 NSString *msg = [[message elementForName:@"body"] stringValue]; NSString *img = [[message elementForName:@"image"] stringValue]; if (!img) { img = @""; } NSString *voice = [[message elementForName:@"voice"] stringValue]; NSString *voiceTime = [[[message elementForName:@"voice"] attributeForName:@"voiceTime"] stringValue]; if (!voice) { voice = @""; voiceTime = @""; } NSString *from = [[message attributeForName:@"from"] stringValue]; NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:msg forKey:@"msg"]; [dict setObject:img forKey:@"photo"]; [dict setObject:voice forKey:@"voice"]; [dict setObject:voiceTime forKey:@"voiceTime"]; [dict setObject:from forKey:@"sender"]; [_messageDelegate newMessageReceived:dict];}//收到好友状态- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence { //取得好友状态 NSString *presenceType = [presence type]; //我的id NSString *userId = [[sender myJID] user]; //对方状态(用user也就相当于强制类型转换成NSString) NSString *presenceFromUser = [[presence from] user]; //如果在列表中把“我”过滤掉 if (![presenceFromUser isEqualToString:userId]) { if ([presenceType isEqualToString:@"available"]) { [_chatDelegate newBuddyOnline:[NSString stringWithFormat:@"%@@%@", presenceFromUser, @"thinkdifferent.local"]]; } if ([presenceType isEqualToString:@"unavailable"]) { [_chatDelegate buddyWentOffline:[NSString stringWithFormat:@"%@@%@", presenceFromUser, @"thinkdifferent.local"]]; } //收到好友请求 if ([presenceType isEqualToString:@"subscribe"]) { [_chatDelegate receivedFriendRequest:[NSString stringWithFormat:@"%@@%@", presenceFromUser, @"thinkdifferent.local"]]; } }}@end
注释中已经写的很详细了,根据服务器传回的消息进行发送消息通知,而设置的代理则用于传输接收到的传递回来的xml数据解析后封装成的字典。
如果对通知机制与代理机制不太熟悉请恶补一下这方面的内容,真的是非常好用!不禁要感叹只有当自己去做程序的时候才能明白其真正的作用。
两个代理
HabberChatDelegate
#import <Foundation/Foundation.h>@protocol HabberChatDelegate <NSObject>//传递上线人的名字- (void)newBuddyOnline:(NSString *)buddyName;//传递下线人的名字- (void)buddyWentOffline:(NSString *)buddyName;//发送与服务器断开连接的信息- (void)didDisconnect;//发送与服务器连接的信息- (void)didConnect;//传送好友申请信息- (void)receivedFriendRequest:(NSString *)presenceFrom;@end
HabberMessageDelegate
#import <Foundation/Foundation.h>@protocol HabberMessageDelegate <NSObject>//就只负责聊天数据的传送- (void)newMessageReceived:(NSDictionary *)messageContent;@end
Model的设置
Statics.h
#import <Foundation/Foundation.h>//这里有三个,专门用于当做存储userDefaults的键值使用static NSString *USERID = @"userId";static NSString *PASS= @"pass";static NSString *SERVER = @"server";@interface Statics : NSObject//获得当前时间+ (NSString *)getCurrentTime;@end
Statics.m
#import "Statics.h"@implementation Statics+ (NSString *)getCurrentTime { NSDate *nowUTC = [NSDate date]; NSDateFormatter *dateFormatter = [NSDateFormatter new]; [dateFormatter setTimeZone:[NSTimeZone localTimeZone]]; [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; return [dateFormatter stringFromDate:nowUTC];}@end
其实关于这个静态方法+ (NSString *)getCurrentTime,作用是获得系统时间显示在聊天cell上的,但是由于已经用了UUChatTableView这个框架,这个方法放在这里没什么意义了,仅供参考。
0 0
- Habber - IOS XMPP 客户端 教程 (二)应用XMPP&代理&全局变量
- Habber - IOS XMPP 客户端 教程 (一)准备工作
- Habber - IOS XMPP 客户端 教程 (三)VC始于LoginViewController、、
- Habber - IOS XMPP 客户端 教程 (四)聊天界面制作
- Habber - IOS XMPP 客户端 教程 (终)总结与反思
- Habber - IOS XMPP 客户端 教程 (零)简介与源码下载
- Habber - IOS XMPP 客户端 教程 (三)着手制作好友列表
- Habber - IOS XMPP 客户端 教程 (续)对方输入状态显示
- xmpp ios客户端二
- XMPP iOS客户端开发(二) 通信
- iOS 之基于XMPP的iphone聊天客户端(二)
- IOS使用XMPP最新教程(二)登陆实现
- XMPP IOS客户端一
- xmpp iOS 客户端三
- IOS XMPP 聊天客户端
- xmpp iOS 聊天客户端
- xmpp iOS 聊天客户端
- 基于XMPP协议的IOS实现(二)XMPP解析
- 期末考试那些事
- Python 中string和unicode的区别
- 258. Add Digits
- 0027 OpenGL的安装及配置
- [Web前端]梳理-DOM.14. DOM.事件,15DOM.事件处理
- Habber - IOS XMPP 客户端 教程 (二)应用XMPP&代理&全局变量
- js 屏蔽浏览器右键菜单
- Spring入门Blog[七、Spring Aop的理解和简单实现]
- 虚拟机类加载机制
- 自己动手整合ssh
- 内存泄漏检测工具
- DialogFragment实现自定义进度条
- [Web前端]梳理-DOM.16. event对象
- 搜索栏UISearchBar和UISearchController