iOS网络层业务层-sina weibo api

1.HTTP请求网络层

封装AFNetworking框架的AFHTTPRequestOperationManager
这样整个项目都使用ZYXHttpTool提供的这两个类方法发送http请求
如果AFN框架更新了只需要更改ZYXHttpTool的这两个类方法即可

ZYXHttpTool.h

//
//  ZYXHttpTool.h
//  网络请求工具类 : 负责整个项目的所有HTTP请求
//
//  Created by zhaoyingxin on 16/8/17.
//  Copyright © 2014年 [email protected]. All rights reserved.
//

#import 

@interface ZYXHttpTool : NSObject

/**
 *  发送一个GET请求
 *
 *  @param urlString    请求路径
 *  @param paramsDict   请求参数
 *  @param success      请求成功后的回调(请将请求成功后想做的事情写到这个block中)
 *  @param failure      请求失败后的回调(请将请求失败后想做的事情写到这个block中)
 */
+ (void)get:(NSString *)urlString
     params:(NSDictionary *)paramsDict
    success:(void (^)(id responseObj))success
    failure:(void (^)(NSError *error))failure;


+ (void)post:(NSString *)urlString
      params:(NSDictionary *)paramsDict
     success:(void (^)(id responseObj))success
     failure:(void (^)(NSError *error))failure;

@end

ZYXHttpTool.m

//
//  ZYXHttpTool.m
//  网络请求工具类 : 负责整个项目的所有HTTP请求
//
//  Created by zhaoyingxin on 16/8/17.
//  Copyright © 2014年 [email protected]. All rights reserved.
//

#import "ZYXHttpTool.h"

#import "AFNetworking.h"

@implementation ZYXHttpTool

+ (void)get:(NSString *)urlString
     params:(NSDictionary *)paramsDict
    success:(void (^)(id))success
    failure:(void (^)(NSError *))failure{
    // 1.获得请求管理者
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
    // 2.发送GET请求
    [mgr    GET:urlString
     parameters:paramsDict
        success:^(AFHTTPRequestOperation *operation, id responseObj) {
            if (success) {
                success(responseObj);
            }
        }
        failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            if (failure) {
                failure(error);
            }
        }
     ];
}


+ (void)post:(NSString *)urlString
      params:(NSDictionary *)paramsDict
     success:(void (^)(id))success
     failure:(void (^)(NSError *))failure{
    // 1.获得请求管理者
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
    // 2.发送POST请求
    [mgr    POST:urlString
      parameters:paramsDict
         success:^(AFHTTPRequestOperation *operation, id responseObj) {
             if (success) {
                 success(responseObj);
             }
         }
         failure:^(AFHTTPRequestOperation *operation, NSError *error) {
             if (failure) {
                 failure(error);
             }
         }
     ];
}

@end

目前应该使用 NSURLSession 基于Session封装 后面补充

2.数据解析层

ZYXBaseTool.h

//
//  ZYXBaseTool.h
//  数据解析层 : 服务器返回JSON字典-->模型
//
//  Created by zhaoyingxin on 16/8/24.
//  Copyright © 2014年 [email protected]. All rights reserved.
//

#import 

@interface ZYXBaseTool : NSObject

+ (void)getWithUrl:(NSString *)urlString
             param:(id)paramModel
       resultClass:(Class)resultClass
           success:(void (^)(id))success
           failure:(void (^)(NSError *))failure;

+ (void)postWithUrl:(NSString *)urlString
              param:(id)paramModel
        resultClass:(Class)resultClass
            success:(void (^)(id))success
            failure:(void (^)(NSError *))failure;

@end

ZYXBaseTool.m

//
//  ZYXBaseTool.m
//  数据解析层 : 服务器返回JSON字典-->模型
//
//  Created by zhaoyingxin on 16/8/24.
//  Copyright © 2014年 [email protected]. All rights reserved.
//

#import "ZYXBaseTool.h"

#import "ZYXHttpTool.h"
#import "MJExtension.h"

@implementation ZYXBaseTool

+ (void)getWithUrl:(NSString *)urlString
             param:(id)paramModel
       resultClass:(Class)resultClass
           success:(void (^)(id))success
           failure:(void (^)(NSError *))failure{
    
    // MJExtension 模型->字典
    NSDictionary *params = [paramModel keyValues];
    
    [ZYXHttpTool get:urlString
              params:params
             success:^(id responseObj) {
                 if (success) {
                     // MJExtension 字典->模型
                     id result = [resultClass objectWithKeyValues:responseObj];
                     success(result);
                 }
             }
             failure:^(NSError *error) {
                 if (failure) {
                     failure(error);
                 }
             }
     ];
}


+ (void)postWithUrl:(NSString *)urlString
              param:(id)paramModel
        resultClass:(Class)resultClass
            success:(void (^)(id))success
            failure:(void (^)(NSError *))failure{
    
    // 模型->字典
    NSDictionary *params = [paramModel keyValues];
    
    [ZYXHttpTool post:urlString
               params:params
              success:^(id responseObj) {
                  if (success) {
                      // 字典->模型
                      id result = [resultClass objectWithKeyValues:responseObj];
                      success(result);
                  }
              }
              failure:^(NSError *error) {
                  if (failure) {
                      failure(error);
                  }
              }
     ];
}

@end

使用了 MJExtension 框架进行字典模型间的互转

3.封装服务器提供的get/post接口

以新浪微博的 OAuth 授权接口为例

获取 AccessToken 的参数模型

#import 

@interface ZYXAccessTokenParam : NSObject

/** 
 true string 申请应用时分配的AppKey。
 */
@property (nonatomic, copy) NSString *client_id;

/**   
 true string 申请应用时分配的AppSecret。
 */
@property (nonatomic, copy) NSString *client_secret;

/**   
 true string 请求的类型,填写authorization_code
 */
@property (nonatomic, copy) NSString *grant_type;

/** 
 true string 调用authorize获得的code值。
 */
@property (nonatomic, copy) NSString *code;

/**
 true string 回调地址,需需与注册应用里的回调地址一致。
 */
@property (nonatomic, copy) NSString *redirect_uri;
@end


#import "ZYXAccessTokenParam.h"

@implementation ZYXAccessTokenParam

@end

微博用户模型
ZYXAccount.h

#import 

@interface ZYXAccount : NSObject 

/** 
 string 用于调用access_token,接口获取授权后的access token。
 */
@property (nonatomic, copy) NSString *access_token;

/** 
 string access_token的生命周期,单位是秒数。
 */
@property (nonatomic, copy) NSString *expires_in;

/** 
 过期时间 
 */
@property (nonatomic, strong) NSDate *expires_time;

/** 
 string 当前授权用户的UID。
 */
@property (nonatomic, copy) NSString *uid;

/**
 用户昵称
 */
@property (nonatomic, copy) NSString *name;

@end

ZYXAccount.m

#import "ZYXAccount.h"

@implementation ZYXAccount

- (void)setExpires_in:(NSString *)expires_in{
    _expires_in =  [expires_in copy];
    // 确定帐号的过期时间 : 帐号创建时间 + 有效期
    NSDate *now = [NSDate date];
    self.expires_time = [now dateByAddingTimeInterval:expires_in.doubleValue];
}

/**
 将对象写入文件的时候调用
 在这个方法中写清楚:要存储哪些对象的哪些属性,以及怎样存储属性
 */
- (void)encodeWithCoder:(NSCoder *)encoder{
    [encoder encodeObject:self.access_token forKey:@"access_token"];
    [encoder encodeObject:self.expires_in forKey:@"expires_in"];
    [encoder encodeObject:self.uid forKey:@"uid"];
    [encoder encodeObject:self.expires_time forKey:@"expires_time"];
    [encoder encodeObject:self.name forKey:@"name"];
}

/**
 当从文件中解析出一个对象的时候调用 
 在这个方法中写清楚:怎么解析文件中的数据
 */
- (id)initWithCoder:(NSCoder *)decoder{
    if (self = [super init]) {
        self.access_token = [decoder decodeObjectForKey:@"access_token"];
        self.expires_in = [decoder decodeObjectForKey:@"expires_in"];
        self.uid = [decoder decodeObjectForKey:@"uid"];
        self.expires_time = [decoder decodeObjectForKey:@"expires_time"];
        self.name = [decoder decodeObjectForKey:@"name"];
    }
    return self;
}
@end

ZYXAccountTool.h

#import "ZYXAccessTokenParam.h"
#import "ZYXBaseTool.h"

@class ZYXAccount;

@interface ZYXAccountTool : ZYXBaseTool

/**
 *  存储帐号
 */
+ (void)save:(ZYXAccount *)account;

/**
 *  读取帐号
 */
+ (ZYXAccount *)account;

/**
 *  获得accesToken
 *
 *  @param paramModel   请求参数
 *  @param success      请求成功后的回调(请将请求成功后想做的事情写到这个block中)
 *  @param failure      请求失败后的回调(请将请求失败后想做的事情写到这个block中)
 */
+ (void)accessTokenWithParam:(ZYXAccessTokenParam *)paramModel
                     success:(void (^)(ZYXAccount *account))success
                     failure:(void (^)(NSError *error))failure;

@end

ZYXAccountTool.m

#define ZYXWeiboAccountFilepath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"weibo_account.data"]

#import "ZYXAccountTool.h"
#import "ZYXAccount.h"

@implementation ZYXAccountTool

+ (void)save:(ZYXAccount *)account{
    [NSKeyedArchiver archiveRootObject:account toFile:ZYXWeiboAccountFilepath];
}

+ (ZYXAccount *)account{
    ZYXAccount *account = [NSKeyedUnarchiver unarchiveObjectWithFile:ZYXWeiboAccountFilepath];
    // 判断帐号是否已经过期
    NSDate *now = [NSDate date];
    if ([now compare:account.expires_time] != NSOrderedAscending) { // 过期
        account = nil;
    }
    return account;
}

+ (void)accessTokenWithParam:(ZYXAccessTokenParam *)paramModel
                     success:(void (^)(ZYXAccount *))success
                     failure:(void (^)(NSError *))failure{
    [self postWithUrl:@"https://api.weibo.com/oauth2/access_token"
                param:paramModel
          resultClass:[ZYXAccount class]
              success:success
              failure:failure];
}

@end

一个完整的网络请求 数据解析 写入数据到沙盒的过程

OAuthViewController.h

#import 
@interface OAuthViewController : UIViewController 
@end

OAuthViewController.m

#import "OAuthViewController.h"

#import "ZYXAccount.h"
#import "ZYXAccountTool.h"
#import "ZYXHttpTool.h"

@implementation OAuthViewController

- (void)viewDidLoad{
    [super viewDidLoad];
    
    // 1.创建UIWebView
    UIWebView *webView = [[UIWebView alloc] init];
    webView.frame = self.view.bounds;
    [self.view addSubview:webView];
    
    // 2.加载登录页面
    NSString *urlStr = [NSString stringWithFormat:
           @"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@",
           ZYXAppKey, ZYXRedirectURI];
    NSURL *url = [NSURL URLWithString:urlStr];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [webView loadRequest:request];
    
    // 3.设置代理
    webView.delegate = self;
}

#pragma mark - UIWebViewDelegate
/**
 UIWebView开始加载资源的时候调用(开始发送请求)
 */
- (void)webViewDidStartLoad:(UIWebView *)webView{
}

/**
 UIWebView加载完毕的时候调用(请求完毕)
 */
- (void)webViewDidFinishLoad:(UIWebView *)webView{
}

/**
 UIWebView加载失败的时候调用(请求失败)
 */
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
}

/**
 UIWebView每当发送一个请求之前,都会先调用这个代理方法(询问代理允不允许加载这个请求)
 @param request 即将发送的请求
 @return YES : 允许加载, NO : 禁止加载
 */
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
 navigationType:(UIWebViewNavigationType)navigationType{
    
    // 1.获得url
    NSString *url = request.URL.absoluteString;
    
    // 2.判断是否为回调地址
    NSRange range = [url rangeOfString:@"code="];
    if (range.length != 0) { // 是回调地址
        // 截取 code= 后面的参数值
        NSUInteger fromIndex = range.location + range.length;
        //用户授权后新浪微博返回的code参数
        NSString *code = [url substringFromIndex:fromIndex];
        // 利用code换取一个accessToken
        [self accessTokenWithCode:code];
        // 禁止加载回调地址
        return NO;
    }
    
    return YES;
}

/**
 根据code获得一个accessToken(发送一个POST请求)
 @param code 授权成功后的请求标记
 */
- (void)accessTokenWithCode:(NSString *)code{
    // 1.封装请求参数
    ZYXAccessTokenParam *paramModel = [[ZYXAccessTokenParam alloc] init];
    paramModel.client_id = ZYXAppKey;
    paramModel.client_secret = ZYXAppSecret;
    paramModel.redirect_uri = ZYXRedirectURI;
    paramModel.grant_type = @"authorization_code";
    paramModel.code = code;
    
    // 2.获得accessToken
    [ZYXAccountTool accessTokenWithParam:paramModel
                                 success:^(ZYXAccount *accountModel) {
                                    // 存储帐号模型
                                    [ZYXAccountTool save:accountModel];
                                 }
                                 failure:^(NSError *error) {
                                    NSLog(@"请求失败--%@", error);
                                 }
     ];
}

@end
// 应用信息
#define ZYXAppKey        @"2507721026"
#define ZYXAppSecret     @"dd92b400310fa5eb9e2fe5bc9c1caa6c"
#define ZYXRedirectURI   @"http://my.oschina.net/u/2333251"

你可能感兴趣的:(iOS网络层业务层-sina weibo api)