测试已测试 | ✗ |
语言语言 | Obj-CObjective C |
许可证 | 定制 |
发布最后发布 | 2014年12月 |
由未指定维护。
依赖 | |
AFNetworking | = 1.1.0 |
SBJson | >= 0 |
SparkAPI
对象被设计为一个独立的目标C接口,用于与 Spark API 一起使用。它通过混合或 OpenID 方法实现了 Spark 认证。通过每种 HTTP 方法提供的 API 调用提供了一个高级 Spark API 接口,并在成功时返回 JSON 结果数组,同时处理客户端的错误,如会话过期。
本项目包含了一个示例 iPad 和 iPhone 应用,该应用使用 SparkAPI
对象通过混合或 OpenID 方法进行认证,搜索列表,查看列表,查看带有照片和标准字段的单个列表,以及查看用户账户。查看 iPad 和 iPhone 的应用截图。
一旦你以 Spark 开发者的身份注册并接收 Spark 客户端 ID 和客户端密钥,打开 SparkAPI.m 文件并设置 sparkClientId
和 sparkClientSecret
类变量。你还必须使用你应用的名称设置 sparkAPIUserAgent
,否则你的 API 请求将不会被接受。《sparkCallbackURL》也可以自定义,但很可能你将开始时使用默认值。
@implementation SparkAPI
// configuration ***************************************************************
static NSString* sparkClientKey = @"<YOUR OAUTH2 CLIENT KEY>";
static NSString* sparkClientSecret = @"<YOUR OAUTH2 CLIENT SECRET>";
static NSString* sparkAPIUserAgent = nil; // set or your API requests will not be successful
static NSString* sparkCallbackURL = @"https://sparkplatform.com/oauth2/callback";
SparkAPI
对象被设计用于与 UIWebView
和 UIWebViewDelegate
对象一起使用,以启动和处理 Spark 认证。
启动认证请求:
要启动混合认证请求,将 getSparkHybridOpenIdURL
封装在一个 NSURLRequest
中,并调用 UIWebView loadRequest:
。
要启动 OpenID 认证请求,将 getSparkOpenIdURL
或 getSparkOpenIdAttributeExchangeURL
封装在一个 NSURLRequest
中,并调用 UIWebView loadRequest:
。
处理认证:
SparkAPI 为处理认证提供两种类方法,并在成功时返回一个 SparkAPI 对象
两者都使用回调块,来接收 Spark API 在成功或失败时发送的异步响应。
+ (BOOL) hybridAuthenticate:(NSURLRequest*)request
success:(void(^)(SparkAPI* sparkAPI))success
failure:(void(^)(NSString* openIdMode, NSString* openIdError, NSError *httpError))failure;
+ (BOOL) openIdAuthenticate:(NSURLRequest*)request
success:(void(^)(SparkAPI* sparkAPI, NSDictionary* parameters))success
failure:(void(^)(NSString* openIdMode, NSString* openIdError))failure;
这些认证方法通常放置在 UIWebViewDelegate 对象中,以响应用户提供 Spark 凭证后生成的 NSURLRequest。参见 LoginViewController.m 以获取示例。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if([SparkAPI hybridAuthenticate:request
success:^(SparkAPI *sparkAPI) {
[self processAuthentication:sparkAPI parameters:nil];
}
failure:^(NSString* openIdMode, NSString* openIdError, NSError *httpError) {
NSString* message = nil;
if(openIdMode)
message = [self handleOpenIdError:openIdMode openIdError:openIdError];
[UIHelper handleFailure:message error:httpError];
}])
return NO;
else
return YES;
}
一旦创建了认证的 SparkAPI
对象,就会提供与四种 HTTP 方法对应的 api 方法,以及通用的 api
方法。与认证方法类似,所有这些方法都使用回调块来接收 Spark API 成功或失败时的异步响应。
成功时,从 Spark 响应对象中解析出结果 JSON 数组,并将其作为参数传递给成功块。
失败时,从返回的 JSON 中解析出 sparkErrorCode
和 sparkErrorMessage
,并将其作为参数传递给失败块。
当 API 返回会话超时的错误代码 错误代码 时,由 SparkAPI
对象自动处理会话更新。
- (void) get:(NSString*)apiCommand
parameters:(NSDictionary*)parameters
success:(void(^)(NSArray *resultsJSON))success
failure:(void(^)(NSInteger sparkErrorCode,
NSString* sparkErrorMessage,
NSError *httpError))failure;
- (void) post:(NSString*)apiCommand
parameters:(NSDictionary*)parameters
success:(void(^)(NSArray *resultsJSON))success
failure:(void(^)(NSInteger sparkErrorCode,
NSString* sparkErrorMessage,
NSError *httpError))failure;
- (void) put:(NSString*)apiCommand
parameters:(NSDictionary*)parameters
success:(void(^)(NSArray *resultsJSON))success
failure:(void(^)(NSInteger sparkErrorCode,
NSString* sparkErrorMessage,
NSError *httpError))failure;
- (void) delete:(NSString*)apiCommand
parameters:(NSDictionary*)parameters
success:(void(^)(NSArray *resultsJSON))success
failure:(void(^)(NSInteger sparkErrorCode,
NSString* sparkErrorMessage,
NSError *httpError))failure;
- (void) api:(NSString*)apiCommand
httpMethod:(NSString*)httpMethod
parameters:(NSDictionary*)parameters
success:(void(^)(NSArray *resultsJSON))success
failure:(void(^)(NSInteger sparkErrorCode,
NSString* sparkErrorMessage,
NSError *httpError))failure;
以下是示例应用程序中对 Spark API 的 /my/account 端点的 API 调用示例。成功时,更新表格视图界面。失败时,向用户展示一个警告视图。
[sparkAPI get:@"/my/account"
parameters:nil
success:^(NSArray *resultsJSON) {
if(resultsJSON && [resultsJSON count] > 0)
{
self.myAccountJSON = [resultsJSON objectAtIndex:0];
[self.tableView reloadData];
[self.activityView stopAnimating];
}
}
failure:^(NSInteger sparkErrorCode,
NSString* sparkErrorMessage,
NSError *httpError) {
[self.activityView stopAnimating];
[UIHelper handleFailure:self code:sparkErrorCode message:sparkErrorMessage error:httpError];
}];
SparkAPI
对象包含基本的日志级别度量,可以控制向控制台输出日志消息。默认情况下,logLevel
属性设置为 SPARK_LOG_LEVEL_INFO
以输出每个 API 调用到控制台。若要将错误输出到控制台,请调用 [SparkAPI setLogLevel:SPARK_LOG_LEVEL_ERROR]
。
示例应用程序为构建自己的 Spark 驱动的 iOS 应用提供了一个非常好的起点。至少,可以重用由 LoginViewController
封装的核心认证功能。
在 AppDelegate
的 didFinishLaunchingWithOptions
方法中,您将需要类似下面的代码来读取任何保存的令牌,并在会话有效的情况下绕过登录来展示您的首页 ViewController
。如果会话无效,则展示 LoginViewController
。
PDKeychainBindings *keychain = [PDKeychainBindings sharedKeychainBindings];
NSString* accessToken = [keychain objectForKey:SPARK_ACCESS_TOKEN];
NSString* refreshToken = [keychain objectForKey:SPARK_REFRESH_TOKEN];
NSString* openIdSparkid = [keychain objectForKey:SPARK_OPENID];
UIViewController *vc = nil;
if((accessToken && refreshToken) || openIdSparkid)
{
self.sparkAPI = [[SparkAPI alloc] initWithAccessToken:accessToken
refreshToken:refreshToken
openId:openIdSparkid];
vc = [UIHelper getHomeViewController];
}
else
{
vc = [[LoginViewController alloc] initWithNibName:([UIHelper iPhone] ? @"LoginViewController" : @"LoginViewController-iPad")
bundle:nil];
vc.title = @"Login";
}
UIViewController *rootVC = nil;
if([UIHelper iPhone])
rootVC = [UIHelper getNavigationController:vc];
else
rootVC = [vc isKindOfClass:[LoginViewController class]] ? vc : [UIHelper getSplitViewController];
在 LoginViewController
中,还需要修改 processAuthentication
方法,以便保存任何会话状态(安全地保存到 Keychain 或 Core Data)并将用户重定向到顶级 ViewController
。
AppDelegate *appDelegate = ((AppDelegate*)[[UIApplication sharedApplication] delegate]);
appDelegate.sparkAPI = sparkAPI;
PDKeychainBindings *keychain = [PDKeychainBindings sharedKeychainBindings];
if(sparkAPI.oauthAccessToken)
[keychain setObject:sparkAPI.oauthAccessToken forKey:SPARK_ACCESS_TOKEN];
if(sparkAPI.oauthRefreshToken)
[keychain setObject:sparkAPI.oauthRefreshToken forKey:SPARK_REFRESH_TOKEN];
if([UIHelper iPhone])
[self.navigationController setViewControllers:[NSArray arrayWithObject:[UIHelper getHomeViewController]]
animated:YES];
else
{
AppDelegate* appDelegate = [UIHelper getAppDelegate];
appDelegate.window.rootViewController = [UIHelper getSplitViewController];
}
测试过的操作系统:iOS 6、iOS 5
测试过的 Xcode 版本:4.5
测试过的设备:iPad 3、iPad 2、iPad mini、iPad 1、iPhone 5、iPhone 4