领域与Alamofire融为一体

本文最初由Christoph Auer发表在我们的博客上

我们想向您介绍如何在Hyphe iOS应用程序中使用Swift库AlamofireRealmObjectMapper ,以便在Hyphe API和我们的iOS客户端之间建立优雅而简单的同步。

  • Alamofire
  • 领域
  • AlamofireObjectMapper
  • 对象映射器

在Hyphe iOS应用程序中, Realm扮演着核心角色。 对于我们而言,重要的是,Hyphe作为通讯录,具有理想的脱机功能。 我们希望向用户交付一个无延迟且几乎在任何地方都可用的应用程序。 因此,应用程序从Hyphe API提取的来自用户的所有相关数据都将本地存储在Realm数据库中。

该应用程序分为两个部分,前端和后端。 在前端不使用Alamofire 。 所有相关数据都可以通过Realm数据库获得。

后端负责Realm数据库与我们的API之间的同步。 另外,何时修改了Realm数据库,后端就会通知限制性展示者,反之亦然。 此外,将通知后端以使Hyphe-API保持最新。 通过这种设计,演示者非常小巧。

在本文中,我们将通过以下示例扩展后端库之间的交互。 我们从一个简单的示例开始,然后逐步将其升级为最终代码。

GET请求传递以下数据:

GET:/ books

[ 
{
"id" : 1,
"title" : "Book A",
"autor" : "Autor 1",
"genre" : "Drama"
},
{
"id" : 2,
"title" : "Book B",
"autor" : "Autor 2",
"genre" : "Myth"
},
{
"id" : 3,
"title" : "Book C",
"autor" : "Autor 3",
"genre" : "Satire"
}
]

关联的Alamofire调用如下所示:

 Alamofire.request(.GET,) 
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}

AlamofireObjectMapperAlamofire的扩展。 该库提供了许多响应处理程序,用于将服务器响应映射到Swift对象。 该库有助于将Alamofire请求的响应映射到书本对象中。 因此,book类必须遵循ObjectMapper库的Mappable协议。

 class Book:Mappable { 
var id = 0
var title = ""
var autor = ""
var genre = ""
//Impl. of Mappable protocol
required convenience init?(_ map: Map) {
self.init()
}
func mapping(map: Map) {
id <- map["id"]
title <- map["title"]
autor <- map["autor"]
genre <- map["genre"]
}
}
Alamofire.request(.GET,url)
.responseArray { (response: Response) in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
let books = response.result.value // books array
//...
}

在将这些书籍对象存储到Realm数据库之前,书籍类必须成为Realm数据模型。 因此,book类必须继承Realm库提供的Object类。 因为Realm库是用Objective-C编写的,所以Realm数据模型的所有非通用属性都需要一个dynamic var属性。

 class Book:Object,Mappable{ 
dynamic var id = 0
dynamic var title = ""
dynamic var autor = ""
dynamic var genre = ""
override static func primaryKey() -> String? {
return "id"
}
//Impl. of Mappable protocol
required convenience init?(_ map: Map) {
self.init()
}
func mapping(map: Map) {
id <- map["id"]
title <- map["title"]
autor <- map["autor"]
genre <- map["genre"]
}
}

现在可以将所有收到的书本对象立即存储到Realm中 。 将add write transition的update选项设置为true ,可以确保仅更新现有的书籍项目,并创建新的书籍项目并将其添加到Realm中
Realm使用主键检测现有的书籍对象,在这种情况下,我们使用书籍项目的服务器ID。

 Alamofire.request(.GET,url) 
.responseArray { (response: Response) in
switch response.result {
case .Success(let books):
do {
let realm = try Realm()
try realm.write {
for book in books {
realm.add(book,update: true)
}
}
} catch let error as NSError {
//TODO: Handle error
}
case .Failure(let error):
//TODO: Handle error
}
}

如果您更仔细地查看“获取请求”,您会发现Alamofire仅需要URL字符串,而AlamofireObjectMapper响应处理程序仅需要遵循Mappable协议的类类型,这是使用泛型的完美案例。 通过更改几行以避免冗余代码,我们可以使用不同的响应对象执行多个GET请求。 因此,所有Realm对象模型都必须遵循Meta协议来提供URL。

 protocol Meta { 
static func url()->String
}
//...
class Book:Object,Mappable,Meta {
dynamic var id = 0
dynamic var title = ""
dynamic var autor = ""
dynamic var genre = ""
override static func primaryKey() -> String? {
return "id"
}
//Impl. of Mappable protocol
required convenience init?(_ map: Map) {
self.init()
}
func mapping(map: Map) {
id <- map["id"]
title <- map["title"]
autor <- map["autor"]
genre <- map["genre"]
}
//Impl. of Meta protocol
static func url()->String {
return "https://bitbucket.org/hyphe/blog-examples/raw/master/fetchData/demoapi/books"
}
}

最终的GET请求如下所示:

 class FetchData { 
static func get (type:T.Type,success:()->Void,fail:(error:NSError)->Void)->Void {
Alamofire.request(Method.GET, type.url())
.responseArray { (response: Response) in
switch response.result {
case .Success(let item):
do {
let realm = try Realm()
try realm.write {
for item in items {
realm.add(item, update: true)
}
} catch let error as NSError {
fail(error:error)
}
success()
case .Failure(let error):
fail(error:error)
}
}
}
}

该GET请求只能在Realm数据库中创建新项目或更新现有项目。 它不会删除从API中删除的Realm对象。
必须根据API单独处理这种情况。

您可以在以下bitbucket存储库中找到一个演示项目。

与往常一样,请随时在下面的评论部分中留下建议。