在上一篇中,我们已经完成了UIDialogWindow自定义弹出窗口组件,本篇接下来完成用户的OAuth授权认证功能,完成后效果如上图。
一、新建名为LoginViewController的UIViewController subclass类型的类文件,新进的时候记得勾上With XIB user interface选项.接下来我们要把这个ViewController添加到window进行显示,继续往下做。
二、打开xcode自动创建的MinBlog4SinaAppDelegate.h文件,添加如下代码:
#import < UIKit / UIKit.h >
@class LoginViewController;
@interface MinBlog4SinaAppDelegate : NSObject < UIApplicationDelegate > {
IBOutlet UIWindow * window;
IBOutlet LoginViewController * loginViewController;
}
@property (nonatomic, retain) IBOutlet UIWindow * window;
@property (nonatomic,retain)IBOutlet LoginViewController * loginViewController;
@end
三、打开MinBlog4SinaAppDelegate.m文件,添加如下代码
#import " MinBlog4SinaAppDelegate.h "
#import " LoginViewController.h "
@implementation MinBlog4SinaAppDelegate
@synthesize window;
@synthesize loginViewController;
- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions {
[application setStatusBarHidden:NO];
[self.window addSubview:loginViewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- ( void )dealloc {
[window release];
[loginViewController release];
[super dealloc];
}
四、接下我们要用到Interface Builder这个工具处理UI方面的工作,双击MainWindow.xib文件,这样IB会打开这个文件,然后从Library面版拖一个View Controller组件到MainWindow.xib中,并且把这个组件的class命名成我们上面建的LoginViewController,如下图所示:
五、接下来鼠标点击选中Min Blog4 Sina App Delegate文件,然后右边的面板中选择Connections,然后能看到一个loginViewController,然后鼠标点击跟在它后面的小圆圈点,然后能拉出一条线,然后拖拽这个线到上面四步骤中新建的LoginViewController组件上完成连接工作,完成后如下图所示:
到此我们完成了把LoginViewController的view添加到window进行显示进行显示的工作了,这样时候可以运行看看,不过运行起来后除了白色的屏幕没有其它任何的东西。
六、打开LoginViewController.h文件,添加如下代码:
#import < UIKit / UIKit.h >
#import " UIDialogWindow.h "
#import " Sqlite.h "
#import " InfoViewController.h "
#import " BlogClient.h "
#import " JSON.h "
@interface LoginViewController : UIViewController {
UIDialogWindow * dialog;
InfoViewController * infoViewController;
NSMutableArray * userList;
BlogClient * blog;
}
@property (nonatomic,retain)NSMutableArray * userList;
@end
上面infoViewController是一个UIViewController,这个是用来提供弹出窗口的内容部分的view用,在上一篇中说过UIDialogWindow组件的内容view是在使用时才提供的,这个infoViewController就是用来给名为dialog的UIDialogWindow组件提供显示内容view。这样我们还需要新建名为InfoViewController的UIViewController subclass类型的类文件,新进的时候记得勾上With XIB user interface选项。
七、如最上面的(图6)所示这个InfoViewController弹出窗口内容就包括一个显示文字描述的TextView;一个点击执行开始的Button,以及左上角的蓝色小图标和“信息提示”,根据这个情况打开上一步新建InfoViewController.h文件声明TextView和Button和按钮事件,至于蓝色小图标和“信息提示”直接用IB在xib文件里加上即可,至于delegate和SEL onClick,是当用户点击开始按钮后会调用delegate的onClick方法,告诉调用这个dialog的UIDialogWindow组件父ViewController按钮被点击了,dialog不处理具体的业务。InfoViewController.h具体代码如下:
#import < UIKit / UIKit.h >
#import " Global.h "
@interface InfoViewController : UIViewController {
id delegate ;
SEL onClick;
IBOutlet UITextView * textView;
IBOutlet UIButton * startBtn;
}
@property (nonatomic,retain)IBOutlet UITextView * textView;
@property (nonatomic,retain)IBOutlet UIButton * startBtn;
- ( void )setDelegate:( id )aDelegate onClick:(SEL)aOnClick;
- (IBAction)startAuth:( id )sender;
@end
八、InfoViewController.m代码中我们用到了前面准备篇中定义在Global下的pngWithPath的方法,具体如下:
#import " InfoViewController.h "
@implementation InfoViewController
@synthesize textView;
@synthesize startBtn;
- ( void )setDelegate:( id )aDelegate onClick:(SEL)aOnClick
{
delegate = aDelegate;
onClick = aOnClick;
}
- (IBAction)startAuth:( id )sender
{
if ( delegate ) {
[ delegate performSelector:onClick withObject: @" start " ] ;
}
}
- ( void )viewDidLoad {
[super viewDidLoad];
textView.font = [UIFont systemFontOfSize: 15 ];
[startBtn setBackgroundImage:[[Global pngWithPath: @" btn_h_bg " ] stretchableImageWithLeftCapWidth: 12.0 topCapHeight: 14.0 ] forState:UIControlStateNormal];
[startBtn setBackgroundImage:[[Global pngWithPath: @" btn_h_bg " ] stretchableImageWithLeftCapWidth: 12.0 topCapHeight: 14.0 ] forState:UIControlStateHighlighted];
}
- ( void )dealloc {
[textView release];
[startBtn release];
[super dealloc];
}
@end
九、接下来我们用IB来处理界面双击InfoViewController.xib打开,然后设定View到合适的大小尺寸,并且比较重要的是要把这个View的Background设置成Clear Color也就是透明了,其他的就是把相应的TextView Button Label拖到View进行适当布局,大概效果如下:
完成控件布局后还需要进行连接操作,完成后如下图:
10、在步骤6中我们只完成LoginViewController.h文件,然后去做InfoViewController了,现在我们继续来完成LoginViewController.m文件,首先是在viewDidLoad方法中进行sqlite数据库中账号检查,并且实例化SDK中的BlogClient对象blog,具体代码如下,对于这个blog对象提供了oauth认证、微博获取、微博发布等一系列跟微博相关的方法,有兴趣的同学可以读一下sdk的源代码,相信会很有帮助。
#define kOAuthConsumerKey @"3983859935"
#define kOAuthConsumerSecret @"201fea7b1e1203a76a10f3be570f5abb"
@implementation LoginViewController
...................
// 如果数据库中已经有帐号记录那么取第一条用户信息进行显示,否则显示授权认证开始对话框
- ( void )showUserInfo
{
Sqlite * sqlite = [[Sqlite alloc] init];
self.userList = [sqlite getUserList];
[sqlite release];
if (self.userList) {
if ([self.userList count] != 0 )
{
infoViewController = [[InfoViewController alloc] init];
dialog = [[UIDialogWindow alloc]initWithView:infoViewController.view];
[infoViewController setDelegate:self onClick:@selector(startAuth:)];
[dialog show];
} else {
// .............................
}
} else {
NSLog( @" no " );
}
}
- ( void )viewDidLoad {
[super viewDidLoad];
[self showUserInfo];
blog = [[BlogClient alloc] initWithConsumerKey:kOAuthConsumerKey consumerSecret:kOAuthConsumerSecret];
}
......................
@end
11、上面的showUserInfo方法中当检查到sqlite数据库中没有账号记录的时候,弹出信息提示窗口提醒用户进行授权认证,当用户点击开始按钮后执行startAuth:方法,代码如下:
- ( void )startAuth:(NSString * )txt
{
[dialog close];
if (blog) {
UIViewController * controller = [blog getOAuthViewController:self];
if (controller) {
[self presentModalViewController: controller animated: YES];
}
} else {
NSLog( @" no blog " );
}
}
12、上面的startAuth会获取blog提供的认证view进行显示,效果见最上面的(图7),让用户输入账号和密码进行授权认证,授权成功后会执行LoginViewController之中的OAuthViewControllerOk方法,取消会执行OAuthViewControllerCancel方法。代码如下:
// 取消授权认证后执行
- ( void )OAuthViewControllerCancel: (NSString * ) text
{
[self showUserInfo];
}
// 完成授权认证后执行
- ( void )OAuthViewControllerOk: (NSString * ) text
{
if (blog) {
[blog show:blog.oauth.userID user_id: @"" screen_name: @"" delegate : self onSuccess:@selector(getUserSuccess: responseText:) onFail:@selector(getUserFail: error:)];
}
}
13、上面的OAuthViewControllerOk,会继续调用blog获取用户信息的方法,把当前用户名、id、头像等信息并且保存到sqlite库中,代码如下:
// 根据id获取用户信息并且保存到数据库
- ( void )getUserSuccess:(NSNumber * )statusCode responseText:(NSString * )data
{
NSObject * obj = [data JSONValue];
User * user = [[User alloc] initWithDictionary:(NSDictionary * )obj];
if (user) {
user.key = [blog.oauth key];
user.secret = [blog.oauth secret];
Sqlite * sqlite = [[Sqlite alloc] init];
BOOL sucess = [sqlite addUser:user];
if (sucess) {
}
[sqlite release];
}
[self showUserInfo];
}
// 根据id获取用户信息失败
- ( void )getUserFail:(NSNumber * )statusCode error:(NSString * )data
{
NSLog( @" get user Error is:%@ " ,data);
}