1、效果演示
2、设计思路
2.1 创建一个OAuth认证控制器,并加载一个WebView
2.2 WebView加载新浪认证的URL(注册新浪帐号并成为新浪开发者),参照 http://open.weibo.com
2.3 使用WebView的代理方法发送RequestToken获取AccessToken
2.3.1 通过返回的URL截取code值即为requestToken
2.3.2 新建一个工具类封装第三方框架(AFNetWorking)的抓取网页数据方法获取JSON
2.3.3 创建一个数据模型保存JSON并归档
2.4 通过判断归档中是否存在AccessToken来修改当前显示的View,如果没有跳转到认证界面,如果有直接跳转到MainView
3、关键代码
SAOAuthController.h
[Objective-C] 纯文本查看 复制代码 //
// SAOAuthController.h
// SianWeibo
//
// Created by yusian on 14-4-14.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAOAuthController : UIViewController
@end
SAOAuthController.m
[Objective-C] 纯文本查看 复制代码 //
// SAOAuthController.m
// SianWeibo
//
// Created by yusian on 14-4-14.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAOAuthController.h"
#import "SACommon.h"
#import "SAHttpTool.h"
#import "SAAccountTool.h"
#import "SAMainController.h"
#import "MBProgressHUD.h"
@interface SAOAuthController () <UIWebViewDelegate>
{
UIWebView *_webView;
}
@end
@implementation SAOAuthController
#pragma mark 设置WebView为主View
-(void)loadView
{
_webView = [[UIWebView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
self.view = _webView;
_webView.delegate = self;
}
#pragma mark 加载web数据到View
- (void)viewDidLoad
{
[super viewDidLoad];
// 1 拼接请求授权的URL
NSString *requestRULString = [NSString stringWithFormat:@"%@?client_id=%@&redirect_uri=%@&display=mobile", kOAuthURL, kAppKey, kRedirect_uri];
NSURL *url = [NSURL URLWithString:requestRULString];
// 2 将请求的页面加载到WebView
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[_webView loadRequest:request];
}
#pragma mark 代理方法获取Token
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// 1、获取全路径,将URL转换成字符串
NSString *url = request.URL.absoluteString;
// 2、查找code范围
NSRange range = [url rangeOfString:@"code="]; // 匹配包含"code="的URL
if (range.length){ // 如果有,取"code="后跟的串,即为requestToken
NSInteger index = range.location + range.length;
NSString *requestToken = [url substringFromIndex:index];
// 3、换取accessToken
[self getAccessToken:requestToken];
return NO;
}
return YES;
}
-(void)getAccessToken:(NSString *)requestToken
{
// SAHttpTool类中自定义方法,实为封装AFNetWorking的方法获取网页数据
[SAHttpTool httpToolPostWithBaseURL:@"https://api.weibo.com" path:@"oauth2/access_token" params:
@{
// 新浪要求必须传递的五个参数
@"client_id" : kAppKey,
@"client_secret" : kAppSecret,
@"grant_type" : @"authorization_code",
@"code" : requestToken,
@"redirect_uri" : kRedirect_uri
// 成功获取JSON
} success:^(id JSON) {
MyLog(@"请求成功");
// 1 将JSON转换成数据模型并归档
SAAccount *account = [SAAccount accountWithDict:JSON];
[[SAAccountTool sharedAccountTool] saveAccount:account];
// 2 跳转到主页面
self.view.window.rootViewController = [[SAMainController alloc]init];
// MyLog(@"%@", JSON);
// 3 清除页面加载提示
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
// 获取信息失败
} failure:^(NSError *error) {
// 1 打印错误提示
MyLog(@"请求失败-%@", [error localizedDescription]);
// 2 清除页面加载提示
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}];
}
#pragma mark - webView的两个代理方法
#pragma mark 开始加载页面时调用
- (void)webViewDidStartLoad:(UIWebView *)webView
{
// 引入第三方框架"MBProgressHUD"添加页面加载提示
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:webView animated:YES];
hud.labelText = @"小龙虾加油中..."; // 设置文字
hud.labelFont = [UIFont systemFontOfSize:14];
}
#pragma mark 页面加载完毕后调用
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// 清除页面加载提示
[MBProgressHUD hideAllHUDsForView:webView animated:YES];
}
@end
SAAccount.h
[Objective-C] 纯文本查看 复制代码 //
// SAAccount.h
// SianWeibo
//
// Created by yusian on 14-4-15.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SAAccount : NSObject <NSCoding>
@property (nonatomic, copy) NSString *accessToken;
@property (nonatomic, copy) NSString *expiresIn;
@property (nonatomic, copy) NSString *remindIn;
@property (nonatomic, copy) NSString *uid;
- (id)initWithDict:(NSDictionary *)dict;
+ (id)accountWithDict:(NSDictionary *)dict;
@end
SAAccount.m
[Objective-C] 纯文本查看 复制代码 //
// SAAccount.m
// SianWeibo
//
// Created by yusian on 14-4-15.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAAccount.h"
@implementation SAAccount
- (id)initWithDict:(NSDictionary *)dict
{
if (self = [super init])
{
self.accessToken = dict[@"access_token"];
self.expiresIn = dict[@"expires_in"];
self.remindIn = dict[@"remind_in"];
self.uid = dict[@"uid"];
}
return self;
}
+ (id)accountWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_accessToken forKey:@"accessToken"];
[aCoder encodeObject:_uid forKey:@"uid"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.accessToken = [aDecoder decodeObjectForKey:@"accessToken"];
self.uid = [aDecoder decodeObjectForKey:@"uid"];
}
return self;
}
@end
SAAccountTool.h
[Objective-C] 纯文本查看 复制代码 //
// SAAccountTool.h
// SianWeibo
//
// Created by yusian on 14-4-15.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SAAccount.h"
@interface SAAccountTool : NSObject
@property (nonatomic, readonly) SAAccount *account;
+ (SAAccountTool *)sharedAccountTool;
- (void)saveAccount:(SAAccount *)account;
@end
SAAccountTool.m
[Objective-C] 纯文本查看 复制代码 //
// SAAccountTool.m
// SianWeibo
//
// Created by yusian on 14-4-15.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAAccountTool.h"
#define kAccountFile [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)[0] stringByAppendingString:@"/account.data"]
@implementation SAAccountTool
// 单例创建三个条件
// 1、全局实例
static SAAccountTool *_instance;
// 2、类创建方法
+ (SAAccountTool *)sharedAccountTool
{
if (_instance) {
_instance = [[self alloc] init];
}
return [[self alloc] init];
}
// 3、重写alloc方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
// 单例在MRC中还需要重写以下三个方法
/******************************
-(oneway void)release
{
return;
}
-(id)retain
{
return self;
}
-(NSUInteger)retainCount
{
return 1;
}
*******************************/
- (id)init
{
if (self = [super init]) {
_account = [NSKeyedUnarchiver unarchiveObjectWithFile:kAccountFile];
}
return self;
}
- (void)saveAccount:(SAAccount *)account
{
_account = account;
[NSKeyedArchiver archiveRootObject:account toFile:kAccountFile];
}
@end
SAHttpTool.h
[Objective-C] 纯文本查看 复制代码 //
// SAHttpTool.h
// SianWeibo
//
// Created by yusian on 14-4-15.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^Success)(id JSON);
typedef void (^Failure)(NSError *error);
@interface SAHttpTool : NSObject
+ (void)httpToolPostWithBaseURL:(NSString *)urlString path:(NSString *)pathString params:(NSDictionary *)params success:(Success)success failure:(Failure)failure;
@end
SAHttpTool.m
[Objective-C] 纯文本查看 复制代码 //
// SAHttpTool.m
// SianWeibo
//
// Created by yusian on 14-4-15.
// Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//
#import "SAHttpTool.h"
#import "AFNetWorking.h"
@implementation SAHttpTool
// 包装第三方框架AFNetWorking,对外提供类似方法
+ (void)httpToolPostWithBaseURL:(NSString *)urlString path:(NSString *)pathString params:(NSDictionary *)params success:(Success)success failure:(Failure)failure
{
// 获取授权
// 1、创建一个Operation
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:urlString]];
NSURLRequest *post = [client requestWithMethod:@"POST" path:pathString parameters:params];
// 2、发送Operation请求
AFJSONRequestOperation *json = [AFJSONRequestOperation JSONRequestOperationWithRequest:post
success:
^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
success(JSON); // 将方法中的实参传给内部的Success Block调用
}
failure:
^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
failure(error); // 将方法中的error传给内部的Failure Block调用
}];
[json start];
}
@end
4、源码下载
相关主题链接
1、ios实战开发之仿新浪微博(第一讲:新特性展示)
2、ios实战开发之仿新浪微博(第二讲:主框架搭建)
3、ios实战开发之仿新浪微博(第三讲:更多界面搭建)
4、ios实战开发之仿新浪微博(第四讲:OAuth认证)
5、ios实战开发之仿新浪微博(第五讲:微博数据加载)
6、ios实战开发之仿新浪微博(第六讲:微博数据展示一)
7、ios实战开发之仿新浪微博(第七讲:微博数据展示二)
8、ios实战开发之仿新浪微博(第八讲:微博数据展示三)
9、ios实战开发之仿新浪微博(第九讲:微博功能完善一)
10、ios实战开发之仿新浪微博(第十讲:微博功能完善二)
11、ios实战开发之仿新浪微博(第十一讲:微博功能完善三)
12、ios实战开发之仿新浪微博(小龙虾发布版)
|