乐高游戏版块 0.1.2

乐高游戏版块 0.1.2

测试测试版
语言语言
许可证 MIT
发布最后发布2015年2月

Logan Wright维护。



 
依赖
AFNetworking>= 0
JSONMapping= 0.1
 

入门

描述乐高游戏版块最好的方式是展示其使用方法。让我们通过spotify网络API查询一些艺术家。以下是从端点的一个示例响应。

{
  "artists" : {
    "href" : "https://api.spotify.com/v1/search?query=tania+bowra&offset=0&limit=20&type=artist",
    "items" : [ {
      "external_urls" : {
        "spotify" : "https://open.spotify.com/artist/08td7MxkoHQkXnWAYD8d6Q"
      },
      "followers" : {
        "href" : null,
        "total" : 12
      },
      "genres" : [ ],
      "href" : "https://api.spotify.com/v1/artists/08td7MxkoHQkXnWAYD8d6Q",
      "id" : "08td7MxkoHQkXnWAYD8d6Q",
      "images" : [ {
        "height" : 640,
        "url" : "https://i.scdn.co/image/f2798ddab0c7b76dc2d270b65c4f67ddef7f6718",
        "width" : 640
      }, {
        "height" : 300,
        "url" : "https://i.scdn.co/image/b414091165ea0f4172089c2fc67bb35aa37cfc55",
        "width" : 300
      }, {
        "height" : 64,
        "url" : "https://i.scdn.co/image/8522fc78be4bf4e83fea8e67bb742e7d3dfe21b4",
        "width" : 64
      } ],
      "name" : "Tania Bowra",
      "popularity" : 4,
      "type" : "artist",
      "uri" : "spotify:artist:08td7MxkoHQkXnWAYD8d6Q"
    } ],
    "limit" : 20,
    "next" : null,
    "offset" : 0,
    "previous" : null,
    "total" : 1
  }
}

在我们的示例中,我们真正关心的是位于键路径artists.items的艺术家对象。我们稍后会使用这个键路径。让我们隔离我们的艺术家对象以进行映射,它看起来像这样

SpotifyArtist Json 表示

{
  "external_urls" : {
    "spotify" : "https://open.spotify.com/artist/08td7MxkoHQkXnWAYD8d6Q"
  },
  "followers" : {
    "href" : null,
    "total" : 12
  },
  "genres" : [ ],
  "href" : "https://api.spotify.com/v1/artists/08td7MxkoHQkXnWAYD8d6Q",
  "id" : "08td7MxkoHQkXnWAYD8d6Q",
  "images" : [ {
    "height" : 640,
    "url" : "https://i.scdn.co/image/f2798ddab0c7b76dc2d270b65c4f67ddef7f6718",
    "width" : 640
  }, {
    "height" : 300,
    "url" : "https://i.scdn.co/image/b414091165ea0f4172089c2fc67bb35aa37cfc55",
    "width" : 300
  }, {
    "height" : 64,
    "url" : "https://i.scdn.co/image/8522fc78be4bf4e83fea8e67bb742e7d3dfe21b4",
    "width" : 64
  } ],
  "name" : "Tania Bowra",
  "popularity" : 4,
  "type" : "artist",
  "uri" : "spotify:artist:08td7MxkoHQkXnWAYD8d6Q"
}

让我们看看它作为Objective-C对象是如何建模的。

模型

SpotifyArtist 模型

首先,我们需要创建我们的对象并确保其符合JSONMappableObject协议。现在我们的对象看起来是这样的。

SpotifyArtist.h

#import <Foundation/Foundation.h>
#import <JSONMapping/JSONMapping.h>

@interface SpotifyArtist : NSObject <JSONMappableObject>
@end

现在让我们填写映射到JSON属性。我们的最终模型头将看起来像这样

SpotifyArtist.h

#import <Foundation/Foundation.h>
#import <JSONMapping/JSONMapping.h>

@interface SpotifyArtist : NSObject <JSONMappableObject>
@property (strong, nonatomic) NSURL *externalSpotifyUrl;
@property (nonatomic) NSInteger numberOfFollowers;
@property (strong, nonatomic) NSArray *genres;
@property (strong, nonatomic) NSURL *url;
@property (copy, nonatomic) NSString *identifier;
@property (strong, nonatomic) NSArray *images;
@property (copy, nonatomic) NSString *name;
@property (nonatomic) NSInteger popularity;
@property (copy, nonatomic) NSString *type;
@property (strong, nonatomic) NSURL *uri;
@end

JSONMappableObject协议要求实现一个返回NSMutableDictionary的实例方法,名为mapping。此方法将在将JSON响应转换为模型对象时在内部使用。建模支持以下语法

mapping[@"<#propertyName#>"] = @"<#associatedJsonKeyPath#>";

此操作试图智能地映射,如果您的属性是一个对应于JSONMappableObject的类,它将自动进行映射。如果您的属性是JSONMappableObject的数组,则需要显式声明类型,因为这无法通过反射发现。为此,您可以使用以下语法

mapping[@"<#arrayPropertyName#>@<#ClassName#>"] = @"<#associatedJsonKeyPath#>";

@语法是JSONMapping的一个重要特性,并且将会经常使用。如果您想有一个更安全的类型,可以使用此便利函数来声明您的键

propertyMap(@"<#propertyName#>", [<#classType#> class])

这种方式映射更安全,这样如果您重构了类名,就不需要执行项目搜索替换键映射。

此语法也可以用来声明一个与其类一起使用的JSONMappableTransformer。更多关于这个我们稍后再说。让我们看看SpotifyArtist的映射

SpotifyArtist.m

#import "SpotifyArtist.h"

@implementation SpotifyArtist
- (NSMutableDictionary *)mapping {
    NSMutableDictionary *mapping = [NSMutableDictionary dictionary];
    // Note keypaths in associated JSON
    mapping[@"externalSpotifyUrl"] = @"external_urls.spotify";
    mapping[@"numberOfFollowers"] = @"followers.total";
    mapping[@"genres"] = @"genres";
    mapping[@"url"] = @"href";
    mapping[@"identifier"] = @"id";
    // Note array type specification
    mapping[@"images@SpotifyImageRef"] = @"images";
    mapping[@"name"] = @"name";
    mapping[@"popularity"] = @"popularity";
    mapping[@"type"] = @"type";
    mapping[@"uri"] = @"uri";
    return mapping;
}
@end

如上所示,我们的images属性是一个数组,我们正在将其内容映射到我们尚未创建的SpotifyImageRef模型。让我们看看在images键中包含的JSON

"images" : [ {
  "height" : 640,
  "url" : "https://i.scdn.co/image/f2798ddab0c7b76dc2d270b65c4f67ddef7f6718",
  "width" : 640
}, {
  "height" : 300,
  "url" : "https://i.scdn.co/image/b414091165ea0f4172089c2fc67bb35aa37cfc55",
  "width" : 300
}, {
  "height" : 64,
  "url" : "https://i.scdn.co/image/8522fc78be4bf4e83fea8e67bb742e7d3dfe21b4",
  "width" : 64
} ]

让我们创建一个类似于以下的模型以表示单个对象

SpotifyImageRef

SpotifyImageRef.h

#import <Foundation/Foundation.h>
#import <JSONMapping/JSONMapping.h>

@interface SpotifyImageRef : NSObject <JSONMappableObject>
@property (nonatomic) NSInteger height;
@property (nonatomic) NSInteger width;
@property (copy, nonatomic) NSURL *url;
@end

注意:如果您愿意,可以在实现文件中声明 JSONMappableObject 协议。这种方法在示例中更为清晰。

SpotifyImageRef.m

#import "SpotifyImageRef.h"

@implementation SpotifyImageRef
- (NSMutableDictionary *)mapping {
    NSMutableDictionary *mapping = [NSMutableDictionary dictionary];
    mapping[@"height"] = @"height";
    mapping[@"width"] = @"width";
    mapping[@"url"] = @"url";
    return mapping;
}
@end

这是一个相对直接的对象,我们的属性名称与 JSON 直接对应。目前,在映射中声明这些属性仍然是必要的,这样做的目的是为了允许绝对控制操作。

就是这样,我们的模型已全部设置完成,现在我们需要为 Spotify API 设置端点。

端点

我更喜欢将端点声明在一个文件中,因为它可以防止在添加端点时需要添加额外的导入,并且许多端点最终会相互依赖。

在您的端点文件中,导入

SpotifyEndpoints.h

#import <Foundation/Foundation.h>
#import <PlayDoh/PDEndpoint.h>

我将要做的第一件事是声明一个基本端点。这样做是为了提供基本 URL 和为特定 API 想要的任何其他请求配置。

#import <Foundation/Foundation.h>
#import <PlayDoh/PDEndpoint.h>

@interface SpotifyBaseEndpoint : PDEndpoint
@end

现在让我们来看看实现

SpotifyEndpoints.m

#import "SpotifyEndpoints.h"
#import "SpotifyArtist.h"

@implementation SpotifyBaseEndpoint
- (NSString *)baseUrl {
    return @"https://api.spotify.com/v1";
}
@end

Spotify 是一个现代且简洁的 API,大多数特性都能很容易地推断出来。如果您想要对基本端点有更多控制,您可以通过添加更多方法重写来创建更复杂的结构。更具体的 API 可能看起来像这样

@implementation GHBaseEndpoint
- (NSSet *)acceptableContentTypes {
    return [NSSet setWithObjects:@"text/html", @"application/json", nil];
}

- (AFHTTPRequestSerializer<AFURLRequestSerialization> *)requestSerializer {
    return [AFJSONRequestSerializer serializer];
}

- (NSDictionary *)headerFields {
    NSMutableDictionary *headerFields = [NSMutableDictionary dictionary];
    headerFields[@"Accept"] = @"application/vnd.github.v3+json";

    NSString *token = [storage accessToken];
    if (token) {
        NSString *tokenHeader = [NSString stringWithFormat:@"Token %@", token];
        headerFields[GHNetworkingHeaderKeyAuthorization] = tokenHeader;
    }

    return headerFields;
}

- (NSString *)baseUrl {
    return @"https://api.github.com";
}
@end

好了,现在回到 Spotify。是时候为我们的搜索添加一个新的端点了。这个端点,以及所有未来的希望使用这个基本 URL 的端点,将继承自我们的 Spotify 基端点。

添加了搜索端点后,我们的端点文件看起来是这样的

SpotifyEndpoints.h

#import <Foundation/Foundation.h>
#import <PlayDoh/PDEndpoint.h>

@interface SpotifyBaseEndpoint : PDEndpoint
@end

// Note subclass
@interface SpotifySearchEndpoint : SpotifyBaseEndpoint
@end

SpotifyEndpoints.m

#import "SpotifyEndpoints.h"
#import "SpotifyArtist.h"

@implementation SpotifyBaseEndpoint
- (NSString *)baseUrl {
    return @"https://api.spotify.com/v1";
}
@end

@implementation SpotifySearchEndpoint
- (Class)returnClass {
    return [SpotifyArtist class];
}
- (NSString *)endpointUrl {
    return @"search";
}
- (NSString *)responseKeyPath {
    return @"artists.items";
}
@end

用于实现的端点至少需要实现 3 个方法:baseUrl、endpointUrl 和 returnClass。在上面的 SpotifySearchEndpoint 中,您会注意到 baseUrl 没有重写。这是因为它继承了 SpotifyBaseEndpoint,该端点重写了 baseUrl。所有未来的子类都可以继承这个基础。

baseUrl - API 的基本 URL。端点将附加到这个 URL 上。

endpointUrl - 端点的 URL。您可以通过在 slug 前面加冒号 : 来声明一个更高级的端点。这些可以智能地映射到对象以生成端点。(关于 slug 映射的更多内容将在后面介绍)。

responseKeyPath - 正如我们在开头所指定的,这是一个简单的示例,我们不需要所有来自响应的信息。我们只想获取位于键路径 artists.items 的艺术家数组。通过在此端点中声明它,我们告诉它。从 URL 端点 search 获取项目,然后从响应中获取键路径 artists.items 的对象。然后将该响应中的对象映射到类型 SpotifyArtist

就是这样,我们现在可以使用搜索 API 了!

使用

一切已设置完成,让我们从服务器获取一些对象!至少,Spotify 搜索端点需要两个参数:query : q 和 type artistalbumtrack。在我们的示例中,我们查询艺术家,所以我们将类型设置为该值。现在我们初始化端点并调用 get。

PDEndpoint *ep = [SpotifySearchEndpoint endpointWithParameters:@{@"q" : @"beyonce", @"type" : @"artist"}];
[ep getWithCompletion:^(id object, NSError *error) {
    NSArray *artists = (NSArray *)object;
    NSLog(@"Got artists: %@ w/ error: %@", artists, error);
}];

由于 Objective-C 允许类型转换的灵活性,我们可以在上面的示例中省略类型转换,并显式替换对象为其类型。

PDEndpoint *ep = [SpotifySearchEndpoint endpointWithParameters:@{@"q" : @"beyonce", @"type" : @"artist"}];
[ep getWithCompletion:^(NSArray *artists, NSError *error) {
    NSLog(@"Got artists: %@ w/ error: %@", artists, error);
}];

这也可以用于单个模型对象,而不仅仅是 NSArray。有关更多信息,请参阅文档中的头部说明!

JSONMappableTransformer

-- 更多文档即将推出,请参阅头文件

SlugMapping

-- 更多文档即将推出,请参阅头文件