在iPhone开发中,自动登录一直是一个问题。因为传统UINavigationController的方式,需要在没有用户触发的情况下自动push出视图控制器。然而经过长时间的尝试,我们发现如果使用ViewController和UINavigationController.pushViewController的方式进行自动登录,会导致UINavigateController的栈内的视图控制器顺序混乱,导致无法正确导航。因此,最终还是只能采用切换UIView的方式实现自动登录。大体思路如下:
首先我们需要分别实现两个UIView:
一个用于呈现登录界面,包含密码、帐号输入框和登录按钮等UI组件以及登录验证的逻辑;
一个用于显示登录成功后的内容界面,比如显示用户操作菜单等;
然后,我们实现一个UIViewController,在其中加入这两个UIView组件,并实现视图切换的逻辑和转换动画。
一、LoginView
首先是实现 UIView 的 initWithFrame 方法,在其中绘制界面,比如:
-(id)initWithFrame:(CGRect)frame{
if(self=[super initWithFrame:frame]){
// 绘制控件代码略
… …
[self performSelector:@selector(login)];
}
return self;
}
界面绘制后,进行自动登录,这是通过调用autoLogin方法实现的:
//自动登录在此实现
- (void)login // 从文件加载用户名密码进行自动登录等
{
// 加载用户名、密码的代码略
… …
// 输入验证的代码略
… …
// 进行登录
[self performSelector:@selector(loginClicked)];
}
loginClicked的方法实现真正的登录验证逻辑,这个方法同时可被用于响应登录按钮的触摸事件:
//登录按钮触摸时触发
-(void)loginClicked{
//验证登录的代码略
… …
if (owner!=nil) {
[owner loginSuccess:success params:params];
}
}
在这里owner被定义为实现了协议LoginOwnerDelegate的对象(id):
id<LoginOwnerDelegate> owner;
@property (assign,nonatomic)id<LoginOwnerDelegate>owner;
而LoginOwnerDelegate协议的定义如下:
@protocol LoginOwnerDelegate<NSObject>
@required
-(void)loginSuccess:(BOOL)success params:(NSDictionary*)params;
@end
在后面,owner属性将被设置为UIViewController实例。因此,要求UIViewController实现LoginOwnerDelegate协议。这样,当LoginView中处理完登录后,将回调UIViewController的loginSuccess:params: 方法。
二、MenuView
这个UIView用于显示登录成功后的功能菜单页面。当点击某个菜单项时,需要回调delegate的menuItemClick 方法:
if (delegate!=nil) {
[delegate menutItemClicked:indexPath.row account:account password:pass userid:userid];
}
delegate协议被定义为实现了协议MenuDelegate的id对象:
id<MenuDelegate> delegate;
}
@property(assign,nonatomic)id<MenuDelegate>delegate;
而MenuDelegate协议定义如下:
@protocol MenuDelegate<NSObject>
@required
-(void)menutItemClicked:(int)index account:(NSString*)acc password:(NSString*)pass userid:(NSString*)uid;
@end
在后面会把delegate属性赋值为UIViewController实例。因此,UIViewController需要实现协议MenuDelegate。
三、UIViewController
从上可知,UIViewController需要实现两个协议:LoginOwnerDelegate和MenuDelegate:
@interface MyViewController:UIViewController
<LoginOwnerDelegate,QXTMenuDelegate>{
… …
}
@end
在加载视图的时候,加入前面的两个UIView:
//初始化UIView
self.view=[[UIView alloc]initWithFrame:CGRectMake(0,0, 320, 400)];
loginCtr=[[LoginvView alloc]initWithFrame:self.view.frame];
loginCtr.owner=self;
[self.view addSubview:loginCtr];
menu=[[MenuView alloc]initWithFrame:self.view.frame];
menu.delegate=self;
[self.view addSubview:menu];
[menu setHidden:YES];
实现时别忘了实现两个协议方法:
#pragma markLoginOwnerDelegate 协议方法
-(void)loginSuccess:(BOOL)success params:(NSDictionary*)params{
if (success) {
// 登录成功,显示MenuView,将LoginView设为隐藏
CATransition *transition=getOglFlipAnimation();
[menu setModel:params];
// 让LoginView和MenuView上下交换位置
[self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
[menu setHidden:NO];
[loginCtr setHidden:YES];
// 设置转换动画
[[self.view layer] addAnimation:transition forKey:@"suckAnimation"];
}else {
//登录失败代码略
… …
}
}
#pragma mark MenuDelegate 协议方法
-(void)menutItemClicked:(int)index account:(NSString*)acc password:(NSString*)pass userid:(NSString*)uid{
// 当点击MenuView中的某个菜单时,进行处理,代码略
… …
}