iOS开发之优秀开源代码解读:RESTKit的使用教程

马上要开始一个关于体育赛事直播的新项目,数据逻辑比较复杂,数据处理这块如果按照以前的积累无疑会选择 AFNetworking+JSONKit+MagicalRecord.这种模式使用起来轻便,可定制性高,缺点就是在处理复杂数据时太费时间。考量得失和项目的需要,决定采用RestKit。其实RestKit在开源社区早就享有盛名,许多人会拿他和AFNetworking相互比较,在我看来两者侧重点不同,没有任何可比性。AFNetworking是一个功能非常齐全的网络数据请求库,侧重于处理各种类型的api风格,提供了远程图片异步加载,上传下载等常用功能,如果项目数据量很小它会是很好的选择。RestKit则是注重从远程数据请求到本地数据解析的存储和流程化业务处理,它专注于RESTful API,如果你项目服务器不是RESTful,那就别考虑了。RestKit包含json解析,object映射和coreData自动存储,很好很强大。如果你非要在这两者之间分个你死我活,请移步  RestKit-vs-AFNetworking-What-are-the-pros-and-cons 。 

之前并无使用RestKit的经验,摘录一篇觉得很不错的入门文章:

原文链接:  Introduction to RestKit Tutorial

翻译正文

你可以连接很多的web service(俗称web服务)来获取精彩有用的信息。举个例子,你可以通过Twitter的web service来获取list和发送Tweets,可以通过连接Foursquare的web service 来获取你附近的餐馆列表。如果你想用使用这些API,你可以直接使用NSURLRequest发起一个网络请求或者使用类似AFNetworking的库。然而还有一个更便捷的方法:使用RestKit!

RestKit是一个非常流行且便于使用的框架。它可以在处理api时候让你少写很多糟糕的代码,比如解析json和映射对象。

在这篇RestKit教程中,我们将要尝试使用FourSquare的api写一个简单的应用来实现现实附近咖啡馆的功能,因为我们都热爱和需要咖啡。

开始

xcode中创建一个Master-View application,输入CoffeeKit作为工程名称,设置device为iPhone

使用RestKit

RestKit由三个部分组成

  • Network :RestKit现在使用AFNetworking v1.3.3作为网络操作层,RestKit的维护者正在升级到AFNetworking 2.0
  • Object Mapping(对象映射): RestKit提供一个接口来直接映射服务器返回的json/xml数据
  • Core Data:RestKit对coreData提供了额外的支持,包括映射远程对象为coreData对象并且进行本地存储

换句话说,这些工作的代码你都不用去写了!

最困难是事情就是安装和配置RestKit,可以选择两种方法:CocoaPods和Git submodule。我宁愿选择CocoaPods (  推荐CocoaPods教程 )。 

Podfile添加内容如下内容,重新pod install即可。

 
platform :ios, '5.0'
pod 'RestKit', '~> 0.20.0'

在AppDelegate.m添加

 
#import <RestKit/RestKit.h>

运行项目,如果没有出错就是安装成功了。

连接Foursquare服务器

查询附近咖啡店需要用到api如下:

https://api.Foursquare.com/v2/venues/search?ll=37.33,-122.03&categoryId=4bf58dd8d48988d1e0931735

这个api返回json格式的数据,地点被写死在latitude: 37.33 and longitude: -122.03 ,大概是苹果的总部位置,categoryId是咖啡店的一个种类标识。

正常情况api会返回:

 

{
    "meta": {
        "code": 200
    },
    "notifications": [
        {
            "item": {
                "unreadCount": 3
            },
            "type": "notificationTray"
        }
    ],
    "response": {
        "confident": true,
        "neighborhoods": [],
        "venues": [
            {
                "categories": [
                    {
                        "icon": {  "prefix": "https://ss1.4sqi.net/img/categories_v2/food/coffeeshop_",  "suffix": ".png"  },
                        "id": "4bf58dd8d48988d1e0931735",
                        "name": "Coffee Shop",
                        "pluralName": "Coffee Shops",
                        "primary": true,
                        "shortName": "Coffee Shop"  }
                ],
                "contact": {
                    "formattedPhone": "(408) 446-9000",
                    "phone": "4084469000",
                    "twitter": "philzcoffee"  },
                "hereNow": {
                    "count": 0,
                    "groups": []  },
                "id": "51630409498eedc7dd88e60b",
                "location": {
                    "address": "20686 Stevens Creek Blvd",
                    "cc": "US",
                    "city": "Cupertino",
                    "country": "United States",
                    "crossStreet": "De Anza Blvd",
                    "distance": 936,
                    "lat": 37.32246179607897,
                    "lng": -122.03470838696346,
                    "postalCode": "95014",
                    "state": "CA"  },
                "name": "Philz Coffee",
                "referralId": "v-1390061483",
                "specials": {
                    "count": 0,
                    "items": []  },
                "stats": {
                    "checkinsCount": 3790,
                    "tipCount": 40,
                    "usersCount": 1460  },
                "verified": true
            },
            {
                "categories": [
                    {
                        "icon": {  "prefix": "https://ss1.4sqi.net/img/categories_v2/food/coffeeshop_",  "suffix": ".png"  },
                        "id": "4bf58dd8d48988d1e0931735",
                        "name": "Coffee Shop",
                        "pluralName": "Coffee Shops",
                        "primary": true,
                        "shortName": "Coffee Shop"  }
                ],
                "contact": {
                    "formattedPhone": "(650) 321-2161",
                    "phone": "6503212161",
                    "twitter": "philz_coffee"  },
                "hereNow": {
                    "count": 0,
                    "groups": []  },
                "id": "4dd1580eb3adb047f5024231",
                "location": {
                    "address": "101 Forest Ave",
                    "cc": "US",
                    "city": "Palo Alto",
                    "country": "United States",
                    "crossStreet": "at Alma St.",
                    "distance": 17063,
                    "lat": 37.442086282055726,
                    "lng": -122.16159119091502,
                    "postalCode": "94301",
                    "state": "CA"  },
                "name": "Philz Coffee",
                "referralId": "v-1390061483",
                "specials": {
                    "count": 0,
                    "items": []  },
                "stats": {
                    "checkinsCount": 14168,
                    "tipCount": 118,
                    "usersCount": 4044  },
                "verified": true
            }
        ]
    }
}

Foursquare提供一个免费的权限来使用他们的Foursquare,但是需要注册app(这和国内新浪等api使用流程相似)  注册页面

开始编码

首先把app的Client ID和Client Secret添加到MasterViewController.m

 
#define kCLIENTID @"Your Foursquare Client ID"
#define kCLIENTSECRET @"Your Foursquare Client Secret

新建一个model命名为Venue,并在MasterViewController.m进行引用

 
@interface Venue : NSObject
@property (nonatomic, strong) NSString *name;
@end

在MasterViewController.m添加

 
- (void)viewDidLoad
{
    [super viewDidLoad];
 
    [self configureRestKit];
    [self loadVenues];
}


- (void)configureRestKit
{
    // initialize AFNetworking HTTPClient
    NSURL *baseURL = [NSURL URLWithString:@"https://api.foursquare.com"];
    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
 
    // initialize RestKit
    RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
 
    // setup object mappings
    RKObjectMapping *venueMapping = [RKObjectMapping mappingForClass:[Venue class]];
    [venueMapping addAttributeMappingsFromArray:@[@"name"]];
 
    // register mappings with the provider using a response descriptor
    RKResponseDescriptor *responseDescriptor = 
        [RKResponseDescriptor responseDescriptorWithMapping:venueMapping 
                                                     method:RKRequestMethodGET 
                                                pathPattern:@"/v2/venues/search" 
                                                    keyPath:@"response.venues" 
                                                statusCodes:[NSIndexSet indexSetWithIndex:200]];
 
    [objectManager addResponseDescriptor:responseDescriptor];
}

RKObjectManager是和RESTful services交互的核心,需要一个AFHTTPClient实例来进行初始化。

RKObjectMapping是用来配置JSON和本地model的映射信息,如果json和本地的model中都有name这个字段,你又需要解析这个字段,那么就要通过addAttributeMappingsFromArray进行添加。

RKResponseDescriptor描述了对HTTP返回数据的映射信息。pathPattern 就是api的具体路径,会被添加到baseURL后面。keyPath 是对象在json数据中的路径。看看上面的json数据,@“response.venues”说明了对象venue所处的逻辑位置,并告诉RestKit去哪找venue。

在 MasterViewController.m添加venues来存储venue变量

 
@interface MasterViewController ()
@property (nonatomic, strong) NSArray *venues;
@end
@implementation MasterViewController

添加如下代码

 
- (void)loadVenues
{
    NSString *latLon = @"37.33,-122.03"; // approximate latLon of The Mothership (a.k.a Apple headquarters)
    NSString *clientID = kCLIENTID;
    NSString *clientSecret = kCLIENTSECRET;
 
    NSDictionary *queryParams = @{@"ll" : latLon,
                                  @"client_id" : clientID,
                                  @"client_secret" : clientSecret,
                                  @"categoryId" :
                                  @"4bf58dd8d48988d1e0931735",
                                  @"v" : @"20140118"};
 
    [[RKObjectManager sharedManager] getObjectsAtPath:@"/v2/venues/search"
                      parameters:queryParams
                         success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                                     _venues = mappingResult.array;
                                     [self.tableView reloadData];
                                 }
                         failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                     NSLog(@"What do you mean by 'there is no coffee?': %@", error);
                                 }];
}

这段代向服务器请求数据,getObjectsAtPath中传递的参数是@“/v2/venues/search”,所以RestKit就会自动查找并使用上文配置的RKResponseDescriptor来映射Venue对象.取到数据后tableView就会正确显示信息了。

显示详细信息

我们想要在cell中显示咖啡店距离用户距离。 查看上文中的json数据,包含的距离的数据是

 
"location": {
    "address": "20686 Stevens Creek Blvd",
    "cc": "US",
    "city": "Cupertino",
    "country": "United States",
    "crossStreet": "De Anza Blvd",
    "distance": 936,
    "lat": 37.32246179607897,
    "lng": -122.03470838696346,
    "postalCode": "95014",
    "state": "CA"
}

新建命名为Location的model

 
@property (nonatomic, strong) NSString *address;
@property (nonatomic, strong) NSString *city;
@property (nonatomic, strong) NSString *country;
@property (nonatomic, strong) NSString *crossStreet;
@property (nonatomic, strong) NSString *postalCode;
@property (nonatomic, strong) NSString *state;
@property (nonatomic, strong) NSNumber *distance;
@property (nonatomic, strong) NSNumber *lat;
@property (nonatomic, strong) NSNumber *lng;

在configureRestKit方法中添加

 
RKObjectMapping *locationMapping = [RKObjectMapping mappingForClass:[Location class]];
[locationMapping addAttributeMappingsFromArray:@[@"address", @"city", @"country", @"crossStreet", @"postalCode", @"state", @"distance", @"lat", @"lng"]];
 
// define relationship mapping
[venueMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"location" toKeyPath:@"location" withMapping:locationMapping]];

通过上面的代码,当请求venue到数据后,可以直接通过venue.location.distance.floatValue来访问距离。 

这篇文章的例子中并未设计coreData对象的映射和存储,可以参照  官方文档 ,用法类似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值