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年 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"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,577评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,623评论 4 59
  • 想念你 身旁的石凳知道 它已被我爱你的话语温润成玉 想念你 周遭的树木知道 你听她们正在微风中婆娑赞颂 想念你 足...
    云妮yunni阅读 284评论 6 3
  • 这是我第二次看《青木瓜之味》,第一次看还是在今年的三月份,那个时候,对于我来说还是一个比较敏感的时期,当时间慢慢慢...
    落行南归nia阅读 1,587评论 3 3