新.XMPP用户登录及注册

一、新建两个storyboard。一个用于实现用户登录及注册,一个负责实现即时通讯主体功能。

在主控制器的storyboard中拖入Tab Bar controller控制器 删除两个分支

再拖入几个Navigation Controller控制器

Tab Bar controllerView controllers连线到对应的Navigation Controller控制器

Navigation Controller控制器的子视图Table View控制器上>修改title标题。

将图片文件夹拖入images.xcassets中。点击Navigation Controller控制器按钮 在右侧修改Bar item名称及图片。

拖入图标时,记录勾选App icon 中的iphone ios6ios7支持。

按钮背影拉伸,show slicing最低支持7.0,如果使用了不想用,得把slicing 选项改成None

 

二、

storyboard中拖入一个View视图到界面(可以方便屏幕适配),再往视图上拖入buttonText添加ToolCategory文件夹

1.输入框需要用户使用回车键  就需要将输入框的delegate属性连线到控制器,再到文件中继承<UITextFieldDelegate>

-(void)textFieldShouldReturn:(UITextField *)textField{//监听文本输入方法

  if (textField ==_userNameText){

  [_passwordText becomeFirstResponder];

  }else{

  //登录

  [self userLogin];

  }

  return YES;

}

2.1.将登录连接方法 -(IBAction)userLogin;

在方法中{

  1.检查用户输入是否完整

  //截断字符串前后的空格(密码除外),从而可以最大程度降低用户输入错误

  NSString *userName = [_userNametext.text trimString]; 

 NSString *password = _passwordText.text;   //有些用户会使用空格做密码 

  if ([userName isEmptyString] || [password isEmptyString]){  //判断用户信息是否输入完整

  UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"提示" message:@"登录信息不完整" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil,nil];

  [alter show];

  // 2. 将用户登录信息写入系统偏好

[[LoginUsersharedLoginUser] setUserName:userName];

[[LoginUsersharedLoginUser] setPassword:password];

[[LoginUsersharedLoginUser] setHostName:hostName];

 

// 3. AppDelegate开始连接

// 告诉AppDelegate,当前是注册用户

NSString *errorMessage = nil;

 

if (button.tag == 1) {

[selfappDelegate].isRegisterUser = YES;

errorMessage = @"注册用户失败!";

} else {

errorMessage = @"用户登录失败!";

}

 

[[selfappDelegate] connectWithCompletion:nilfailed:^{

UIAlertView *alter = [[UIAlertViewalloc] initWithTitle:@"提示"message:errorMessage delegate:nilcancelButtonTitle:@"确定"otherButtonTitles:nil, nil];

 

[alter show];

 

if (button.tag == 1) {

// 注册用户失败通常是因为用户名重复

[_userNameTextbecomeFirstResponder];

} else {

// 登录失败通常是密码输入错误

[_passwordTextsetText:@""];

[_passwordTextbecomeFirstResponder];

}

}];


  return;

  }

2.2.AppDelegate开始连接、添加AppDelegate.h头文件

 添加 -(AppDelegate *)appDelegate{ //并初始化这个方法

    return [[UIApplication sharedApplication] delegate];

    }

2.3.viewDidLoad中添加拉伸按钮图片

// 1) 登录按钮

UIImage *loginImage = [UIImageimageNamed:@"LoginGreenBigBtn"];

loginImage = [loginImage stretchableImageWithLeftCapWidth:loginImage.size.width * 0.5topCapHeight:loginImage.size.height * 0.5];


相对上面布局:选中两个要对齐的元素,点击.Editor>pin>Vertical Spacing



2.4AppDelegate.m文件中

interface中新建方法:遵守XMPPStreamDelegate协议可以方便编写代码(不写也可以)

  1.设置XMPPStream>setupStream

  2.通知服务器用户上线>goOnline

  3.通知服务器用户下线>goOffline

  4.连接到服务器>connect

  5.与服务器断开连接>disConnect

并实现。

3.//设置setupStream实例化流。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

这个方法中// 2. 设置XMPPStream并调用[selfsetupStream];

。在.h头文件中定义XMPP相关的属性的方法定义> 全局的XMPPStream,只读属性readonly

{

这里可以使用断言,就可以不用判断xmppStream是否为nil,等于nil才实例化。

// 0. 方法被调用时,要求_xmppStream必须为nil,否则通过断言提示程序员,并终止程序运行!

NSAssert(_xmppStream == nil, @"XMPPStream被多次实例化!");


  1.实例化流

  _xmppStream [[XMPPStream alloc] init];

  


 // 2 设置重新连接模块,需要在XMPPStream文件中打开XMPPReconnect文件

,实例化,激活就可以使用了。在代理中添加成员变量XMPPReconnect *_xmppReconnect;

 

_xmppReconnect = [[XMPPReconnect alloc] init];

  // 3将重新连接模块添加到XMPPStream

[_xmppReconnect activate:_xmppStream];

 // 4.添加代理。因为所有网络请求都是做基于网络的数据处理,跟 UI无关,因此可以让代理yyifd其化线程中 ,从而提高程序的运行性能

  [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)];


}

4.//注销已注册的扩展模块。当内存不足或注销的时候 销毁XMPPStream并注销已注册的扩展模块

- (void)teardownStream

{

// 1.删除代理

[_xmppStream removeDelegate:self];

 

// 2. 取消激活在setupStream方法中激活的扩展模块

[_xmppReconnectdeactivate];

 

// 3. 断开XMPPStream的连接

[_xmppStreamdisconnect];

 

// 4. 内存清理

_xmppStream = nil;

_xmppReconnect = nil;

}

5.- (void)dealloc

{

// 释放XMPP相关对象及扩展模块

[self teardownStream];

}

//通知服务器用户上线

6.goOnline{

  //1。实例化一个上线报告,默认类型为:available

  XMPPPresence *presence = [XMPPPressence presence];

  [_xmppStream sendElement:presence];  //这个方法没有回调,只通知我的好友

}

7.goOffline{

  //1.实例化一个下线报告

    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];

  //2.发送presence给服务器,通知服务器客户端下线

    [_xmppStream sendElement:presence];

}

8.保持用户登录信息

AppDelegate.h文件中 定义一个连接到服务器的方法 判断是否正确失败块代

typedef void(^CompletionBlock)();


-(void)connectWithUserName:(CompletionBlock *)completion password:(CompletionBlock *)faild; //completion 正确块代码 faild错误块代码方法新建一个类LoginUser.封装一个单独的类来保持用户登录信息

.h文件中添加Singleton.h头文件在@interface定义属性

single_interface(LoginUser)

@property (strong, nonatomic) NSString *userName;

@property (strong, nonatomic) NSString *password;

@property (strong, nonatomic) NSString *

@property (strong, nonatomic, readonly) NSString *myJIDName;

hostName;

再到.m文件中定义single_implementation(LoginUser)和导入NSString+Helper.h头文件

以及定义#用户名,密码,服务器

#define kXMPPUserNameKey    @"xmppUserName"

      #define kXMPPPasswordKey    @"xmppPassword"

      #define kXMPPHostNameKey    @"xmppHostName"

实现方法

  - (NSString *)loadStringFromDefaultsWithKey:(NSString *)key

  {

NSString *str = [[NSUserDefaults standardUserDefaults] stringForKey:key]; 

return (str) ? str : @"";

  }

  - (NSString *)userName

  { return [self loadStringFromDefaultsWithKey:kXMPPUserNameKey];}


  - (void)setUserName:(NSString *)userName

  { [userName saveToNSDefaultsWithKey:kXMPPUserNameKey];}


  - (NSString *)password

  {return [self loadStringFromDefaultsWithKey:kXMPPPasswordKey];}


  - (void)setPassword:(NSString *)password

  { [password saveToNSDefaultsWithKey:kXMPPPasswordKey];}


  - (NSString *)hostName

  { return [self loadStringFromDefaultsWithKey:kXMPPHostNameKey];}


  - (void)setHostName:(NSString *)hostName

  { [hostName saveToNSDefaultsWithKey:kXMPPHostNameKey];}


- (NSString *)myJIDName

{ return [NSStringstringWithFormat:@"%@@%@", self.userName, self.hostName];

}



9.连接connnect.在代理. m文件导入保持用户登录信息LoginUser头文件

 

// 1. 如果XMPPStream当前已经连接,直接返回 就不会需调用”[self setupStream];“

if ([_xmppStreamisConnected]) { return; }

// 2. 指定用户名、主机(服务器),连接时不需要password

NSString *hostName = [[LoginUsersharedLoginUser] hostName];

NSString *userName = [[LoginUsersharedLoginUser] myJIDName];

// 3. 设置XMPPStreamJID和主机

[_xmppStreamsetMyJID:[XMPPJIDjidWithString:userName]];

[_xmppStreamsetHostName:hostName];

 

// 4. 开始连接

NSError *error = nil;

[_xmppStreamconnectWithTimeout:XMPPStreamTimeoutNoneerror:&error];

 

// 提示:如果没有指定JIDhostName,才会出错,其他都不出错。

if (error) {

NSLog(@"连接请求发送出错 - %@", error.localizedDescription);

} else {

NSLog(@"连接请求发送成功!");

}

}

//断开连接

desConnect{

  //通知服务器下线

  [self goOffline];

  //XMPPStream断开连接

  [_xmppStream disconnect];

}



#pragma mark – 代理方法

.h文件中,定义方法是否注册用户标示

@property (assign, nonatomic) BOOL isRegisterUser;

@property ( assign,nonatomic) BOOL isUserLogon;

.m 文件中继续追加成员变量:

CompletionBlock _completionBlock; // 成功的块代码

CompletionBlock _faildBlock; // 失败的块代码



#pragma mark 连接完成(如果服务器地址不对,就不会调用此方法)

- (void)xmppStreamDidConnect:(XMPPStream *)sender

{

// 从系统偏好读取用户密码

NSString *password = [[LoginUsersharedLoginUser] password];

 

if (_isRegisterUser) {

// 用户注册,发送注册请求

[_xmppStreamregisterWithPassword:password error:nil];

} else {

// 用户登录,发送身份验证请求

[_xmppStreamauthenticateWithPassword:password error:nil];

}

}


#pragma mark 注册成功

- (void)xmppStreamDidRegister:(XMPPStream *)sender

{

_isRegisterUser = NO;

 

// 注册成功,直接发送验证身份请求,从而触发后续的操作

[_xmppStreamauthenticateWithPassword:[LoginUsersharedLoginUser].passworderror:nil];

}


#pragma mark 注册失败(用户名已经存在)

- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error

{

_isRegisterUser = NO;

if (_faildBlock != nil) {

dispatch_async(dispatch_get_main_queue(), ^{

_faildBlock();

});

}

}


#pragma mark 身份验证通过

- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender

{

if (_completionBlock != nil) {

dispatch_async(dispatch_get_main_queue(), ^{

_completionBlock();

});

}

 

// 通知服务器用户上线

[selfgoOnline];

 

// 显示主Storyboard

[selfshowStoryboardWithLogonState:YES];

}


定义头文件#define kNotificationUserLogonState @"NotificationUserLogon"

.m文件中

#pragma mark 根据用户登录状态加载对应的Storyboard显示

- (void)showStoryboardWithLogonState:(BOOL)isUserLogon

{

UIStoryboard *storyboard = nil;

 

if (isUserLogon) {

// 显示Main.storyboard

storyboard = [UIStoryboardstoryboardWithName:@"Main"bundle:nil];

} else {

// 显示Login.sotryboard

storyboard = [UIStoryboardstoryboardWithName:@"Login"bundle:nil];

}

 

// 在主线程队列负责切换Storyboard,而不影响后台代理的数据处理

dispatch_async(dispatch_get_main_queue(), ^{

// 如果在项目属性中,没有指定主界面(启动的Storyboardself.window不会被实例化)

// Storyboard的初始视图控制器设置为windowrootViewController

[self.windowsetRootViewController:storyboard.instantiateInitialViewController];

 

if (!self.window.isKeyWindow) {

[self.windowmakeKeyAndVisible];

}

});

}



#pragma mark 密码错误,身份验证失败

- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error

{

if (_faildBlock != nil) {

dispatch_async(dispatch_get_main_queue(), ^{

_faildBlock();

});

}

 

// 显示用户登录Storyboard

[selfshowStoryboardWithLogonState:NO];

}


- (void)applicationDidBecomeActive:(UIApplication *)application

{

// 应用程序被激活后,直接连接,使用系统偏好中的保存的用户记录登录

// 从而实现自动登录的效果!

[selfconnect];

}

- (void)applicationWillResignActive:(UIApplication *)application

{

[selfdisconnect];

}


添加一个注销按钮,退出到登录界面

新建一个UITableViewController控制器。选择Table View控制器连线到点M文件中。


在该方法中。添加AppDelegate.h头文件并在代理头文件写入注册方法。

在代理.M文件中实现方法{

// 1. 通知服务器下线,并断开连接

[selfdisconnect];

// 2. 显示用户登录Storyboard

[selfshowStoryboardWithLogonState:NO];


logout方法中 设置_isUserLogon = No;

在注销文件中,初始化AppDelegate方法

在注销按钮中调用[self appDelegate] logout];就能实现注销用户登录了


----------------



转载于:https://www.cnblogs.com/qq907374866/p/4253513.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值