服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - IOS开发用户登录注册模块所遇到的问题

IOS开发用户登录注册模块所遇到的问题

2021-01-05 12:21华过的痕迹 IOS

最近和另外一位同事负责公司登录和用户中心模块的开发工作。通过本文给大家分享IOS开发用户登录注册模块所遇到的问题,感兴趣的朋友一起学习吧

最近和另外一位同事负责公司登录和用户中心模块的开发工作,开发周期计划两周,减去和产品和接口的协调时间,再减去由于原型图和接口的问题,导致强迫症纠结症状高发,情绪不稳定耗费的时间,能在两周基本完成也算是个不小的奇迹了。本文就总结一下如何满足产品需要的情况下,高效开发一个登录注册模块。

1.利用继承解决界面重复性功能。通常登录注册会有一个独立的设计,而模块内部会有有相似的背景,相似的导航栏样式,相似返回和退出行为,相似的输入框,按钮样式等。

IOS开发用户登录注册模块所遇到的问题IOS开发用户登录注册模块所遇到的问题IOS开发用户登录注册模块所遇到的问题

比如上面的的注册和登录模块,就有相同的返回按钮,相同的背景,相同的导航栏样式,甚至相同的按钮和输入框样式。所以为了加快我们的开发,我们完全先定义一个父控制器,然后通过的继承实现多态,从而实现我们快速设计页面和基本功能的实现。下图是我的个人项目《丁丁印记》的登录注册模块的目录结构,其中hooentrybaseviewcontroller就定义了这个模块通用的行为和样式:

IOS开发用户登录注册模块所遇到的问题

2.弹出键盘和退出键盘机制开发。

这点使我们开发者容易忽略的一点,我也因为看到一些app因为弹出键盘遮挡输入,导致怒删app的行为。这模块的设计就根据产品的设计来决定采用什么代码实现我们的目的了。

•单击空白区域退出键盘代码:

?
1
2
3
4
5
6
7
8
uitapgesturerecognizer *tap = [[uitapgesturerecognizer alloc] initwithtarget:self action:@selector(closekeyboard:)];
tap.numberoftapsrequired = 1;
tap.numberoftouchesrequired = 1;
[self.view addgesturerecognizer:tap];
- (void)closekeyboard:(id)sender
{
[self.view endediting:yes];
}

•避免键盘遮挡,登录表单或按钮上移代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)textviewdidbeginediting:(uitextfield *)textview
{
cgrect frame = textview.frame;
int offset = frame.origin.y + 120 - (self.view.frame.size.height - 216.0);//键盘高度216
nstimeinterval animationduration = 0.30f;
[uiview beginanimations:@"resizeforkeyboard" context:nil];
[uiview setanimationduration:animationduration];
float width = self.view.frame.size.width;
float height = self.view.frame.size.height;
if(offset > 0)
{
cgrect rect = cgrectmake(0.0f, -offset,width,height);
self.view.frame = rect;
}
[uiview commitanimations];
}

3.接入第三方登录,必须要判断用户是否安装该第三方客户端,否则苹果可能审核无法通过。血的教训。

  比如我的app《丁丁印记》接入了qq登录功能,程序会客户端是否安装了qq,如果未安装则隐藏qq登录图标。

?
1
2
3
4
if (![qqapi isqqinstalled]) {
self.qqloginbutton.hidden = yes;
self.qqloginlabel.hidden = yes;
}

4.特殊情景处理。这容易是一个空白点,通常年轻的开发的者不会考虑到这一块,而通常产品和ue也不太会记得定义清楚临界点的行为。

•  加载状态。当用户发起登录或者注册请求时需要给用户友好的提示。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma mark - 登录按钮点击
- (ibaction)login:(uibutton *)sender {
if([self.usernametextfield.text isempty] || [self.passwordtextfield.text isempty]){
[svprogresshud showerrorwithstatus:@"用户名或密码不能为空"];
}else{
__weak typeof(self) weakself = self;
[[hoousermanager manager] loginwithusername:self.usernametextfield.text andpassword:self.passwordtextfield.text block:^(bmobuser *user, nserror *error) {
__strong __typeof(weakself)strongself = weakself;
if (error) {
[svprogresshud showerrorwithstatus:@"登录失败"];
}else if(user){
[svprogresshud showsuccesswithstatus:@"登录成功"];
[strongself loginsuccessdismiss];
}
}];
}
}

•  账号或者密码各种错误判断

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
nsstring *emailstr;
nsstring *phonestr;
nsstring *passwordstr = weakself.passwordview.inputtextfield.text;
emailstr = weakself.accountview.inputtextfield.text;
if (![nsstring validateemail:emailstr] || !emailstr.length) {
[weakself showerrortipviewwithmessage:@"邮箱格式错误"];
return;
}
} else {
phonestr = weakself.accountview.inputtextfield.text;
if (phonestr.length < 5) {
[weakself showerrortipviewwithmessage:@"手机长度错误")];
return;
}
if ([weakself.accountview.countrycode isequaltostring:@"+86"]) {
if (![phonestr isvalidatemobilenumber]) {
[weakself showerrortipviewwithmessage:@"手机号码格式错误")];
return;
}
}
}
if (passwordstr.length < kpasswordminlength) {
[weakself showerrortipviewwithmessage:atlocalizedstring(@"密码长度超过少于6个字符")];
return;
}
if (passwordstr.length > kpasswordmaxlength) {
[weakself showerrortipviewwithmessage:@"密码长度超过20个字符")];
return;
}

5.手机找回密码,发送验证码按钮的处理。这个行为也容易被产品忽略需要我们开发者主动想到,然后跟产品确定这个需求,然后确定按钮的触发后的行为,否则用户可能多次点击发送验证码,这会造成服务器负担,并且可能返回给用户多条短信,造成困扰。下面这段代码可以实现单击验证码按钮,然后倒计时2分钟后恢复按钮的可点击状态。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- (void)verifedcodebuttonwithtitle:(nsstring *)title andnewtitle:(nsstring *)newtitle {
ws(weakself);
__block int timeout = ktimeout;
dispatch_queue_t queue = dispatch_get_global_queue(dispatch_queue_priority_default, 0);
dispatch_source_t _timer = dispatch_source_create(dispatch_source_type_timer, 0, 0,queue);
dispatch_source_set_timer(_timer,dispatch_walltime(null, 0),1.0*nsec_per_sec, 0);
dispatch_source_set_event_handler(_timer, ^{
if(timeout<=0){
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
[weakself settitle:title forstate:uicontrolstatenormal];
weakself.userinteractionenabled = yes;
});
}else{
int seconds = timeout;
nsstring *strtime = [nsstring stringwithformat:@"%.2d", seconds];
dispatch_async(dispatch_get_main_queue(), ^{
[uiview beginanimations:nil context:nil];
[uiview setanimationduration:1];
[weakself settitle:[nsstring stringwithformat:@"%@(%@)",newtitle,strtime] forstate:uicontrolstatenormal];
[uiview commitanimations];
weakself.userinteractionenabled = no;
});
timeout--;
}
});
dispatch_resume(_timer);
}

5.用户登录信息和状态持久化。我们通常会有业务层处理登录的数据的持久,并且使用单例,但是不能依赖单例记录用状态,因为用户可能会退出,所以需要从沙盒去读取用户状态的字段是否存在,如用户的id,或者accesstoken。

  下面这段代码,用来持久化用户信息

-

?
1
2
3
4
5
6
7
8
(void)saveuserinfowithdata:(nsdictionary *)dict {
nsstring *userid = dict[kuserid];
nsstring *email = dict[kemail];
nsstring *mobile = dict[kmobile];
[hoonsuserdefaultserialzer setobject:memberid forkey:kuserid];
[hoonsuserdefaultserialzer setobject:email forkey:kemail];
[hoonsuserdefaultserialzer setobject:mobile forkey:kmobile];
}

5.对外开发用户信息的接口。封装我们的模块。对外提供我们的接口,通常其他页面需要判断用户是否登录,也可能需要用户的唯一标示符来请求数据。这一块如果我们做的混乱,则容易导致其他页面获取用户信息的随意性,比如给他们开发了读取沙盒里读取用户信息的字段。我们应该在登录模块统一其他页面获取这些用户信息的行为。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#import <foundation/foundation.h>
#import "hoosingleton.h"
@interface hoousermanager : nsobject
@property (nonatomic, strong) nsstring *userid;
singletonh(manager)
/**
* verify user if login or not
*
* @return if login in return yes ,otherwise return no
*/
- (bool)isuserlogin;
/**
* login out
*/
- (void)loginout;
@end
#import "hoousermanager.h"
#import "hoonsuserdefaultserialzer.h"
static nsstring * const kmobile = @"mobile";
static nsstring * const kemail = @"email";
static nsstring * const kuserid = @"userid";
@implementation hoousermanager
singletonm(manager)
#pragma mark - getter and setter
- (nsstring *)userid {
nsstring *userid = [hoonsuserdefaultserialzer objectforkey:kuserid];
return userid;
}
- (bool)isuserlogin {
nsstring *userid = [hoonsuserdefaultserialzer objectforkey:kuserid];
if (userid.length) {
return yes;
}
return no;
}
- (void)loginout {
[hoonsuserdefaultserialzer removeobjectforkey:kmobile];
[hoonsuserdefaultserialzer removeobjectforkey:kemail];
[hoonsuserdefaultserialzer removeobjectforkey:kuseid];
}
@end

6.其他。

  其实为了更好的用户体验,我们还会提供其他功能,如明文显示密码选择按钮、从服务器读取邮箱格式提示、错误字符纠正、当然还有最重要的动画效果。

延伸 · 阅读

精彩推荐
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17