美文网首页iOS
iOS网络层业务层-sina weibo api

iOS网络层业务层-sina weibo api

作者: solozyx | 来源:发表于2016-08-17 17:49 被阅读73次

    1.HTTP请求网络层

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

    ZYXHttpTool.h

    //
    //  ZYXHttpTool.h
    //  网络请求工具类 : 负责整个项目的所有HTTP请求
    //
    //  Created by zhaoyingxin on 16/8/17.
    //  Copyright © 2014年 zhaoyingxin@aliyun.com. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @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年 zhaoyingxin@aliyun.com. 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年 zhaoyingxin@aliyun.com. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @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年 zhaoyingxin@aliyun.com. 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 <Foundation/Foundation.h>
    
    @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 <Foundation/Foundation.h>
    
    @interface ZYXAccount : NSObject <NSCoding>
    
    /** 
     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 <UIKit/UIKit.h>
    @interface OAuthViewController : UIViewController <UIWebViewDelegate>
    @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

        本文链接:https://www.haomeiwen.com/subject/rvwmsttx.html