Swift + Alamofire + ObjectMapper + Realm [Swift3 대응]
수탁 안건에서는 거의 필수 기능이라고 할 수 있다
라는 흐름.
모처럼 나우한 언어인 Swift이니까, 이케 하고 있는 라이브러리로 키메키메인 코딩을 하고 싶다!
그래서 Swift나 새로운 라이브러리의 조사가 끝나고, 얼른 샘플을 만들어 보았습니다.
샘플
샘플을 여기에 올려 보았습니다.
Github - SatoshiN21/RealmSample
※자연스럽게 Swift3에 대응하고 있습니다.
이번에는 하부의 IT 카테고리의 핫 엔트리 RSS를 JSON 형식으로 취득하고 있습니다.
나우한 Material Design의 CardView 같은 모양으로 해 보았습니다.
1. JSON 취득
Alamofire는 부의 피드 정보를 얻고 있습니다.
핫 엔트리는 RSS 형식으로 배포되었으므로 google의 API을 사용하여 JSON 형식으로 변환했습니다.
import Alamofire
import SwiftyJSON
// google JSON api + hatena bookmark hotentry
let hotEntryUrl = "https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://b.hatena.ne.jp/hotentry/it.rss&num=100"
// Alamofireを用いてGETリクエスト
Alamofire.request(hotEntryUrl).responseJSON { (response) in
guard response.result.isSuccess, let value = response.result.value else {
// FIXME:便宜上こちら無視してますが、実装時はエラーのハンドリングを行う必要があります
return
}
// SwiftyJSON方式
let json = JSON(value)
}
얻은 JSON을 SwiftyJSON 형식으로 변환하고 다시 실행합니다.
이번 샘플에서는 리퀘스트 에러시의 처리는 구현하고 있지 않으므로, 주의해 주세요!
2. JSON을 구문 분석하여 DB에 삽입
SwiftyJSON 형식으로 하면 퍼스 작업이 되겠네요! 체인 모양으로 원하는 요소를 얻을 수 있습니다.
항목 목록을 가져옵니다.
let json = JSON(responseObject!)
let entries = json["responseData"]["feed"]["entries"]
ObjectMapper를 사용하여 Entry 객체에 매핑합니다.
ObjectMapper와 Realm을 공존시키는 방법은 gologo13 님의 게시물 를 참고로 했습니다.
import ObjectMapper
realm.beginWrite()
// JSONをEntryオブジェクトにマッピング
for (_, subJson) in entries {
if let entry = Mapper<Entry>().map(JSONObject: subJson.dictionaryObject) {
realm.add(entry, update: true)
}
}
realm.commitWrite()
RealmSwift.Object를 상속한 Entry 객체 내의 사양은 거의 참고로 한 기사와 같습니다만,
게시일 날짜를 사용자 정의 DateTransform에서 Date로 변환하고 있습니다.
extension Entry : Mappable {
func mapping(map: Map) {
content <- map["content"]
link <- map["link"]
publishedDate <- (map["publishedDate"] , EntryDateTransform())
title <- map["title"]
contentSnippet <- map["contentSnippet"]
}
}
// 独自定義したDateTransform
// フォーマットとNSLocaleを指定してStringをNSDateに変換
class EntryDateTransform : DateTransform {
override func transformFromJSON(_ value: Any?) -> Date? {
if let dateStr = value as? String {
return Date.dateWithString(
dateStr,
format: "E, dd MMM yyyy HH:mm:ss zzzz" ,
locale : Locale(identifier: "en_US"))
}
return nil
}
}
extension Date {
public static func dateWithString(_ dateStr : String? , format : String, locale : Locale) ->Date? {
guard let dateStr = dateStr else {
return nil
}
let df : DateFormatter = DateFormatter()
df.locale = Locale(identifier: "en_US")
df.timeZone = TimeZone.current
df.dateFormat = format
return df.date(from: dateStr)
}
}
3. DB 값을 TableView에 표시
Realm의 갱신이 발생한 타이밍에 UITableView#reloadData()를 실행해, UITableView의 표시를 갱신.
RealmSwift.Object를 상속한 클래스에서 objects(type: Object.Type)를 호출하면 DB에 저장된 모든 값을 얻을 수 있습니다.
func updateTableView() {
do {
self.entries = try Realm().objects(Entry.self).sorted(by: { (entry1, entry2) -> Bool in
let res = entry1.publishedDate.compare(entry2.publishedDate)
return (res == .orderedAscending || res == .orderedSame)
})
}catch {}
tableView.reloadData()
}
// MARK:- UITableView DataSource / Delegate
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let entries = entries {
return entries.count
}
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier") as! EntryTableViewCell
// if entries have been nil,"cellForRowAtIndexPath:indexPath:" isn't called.
let entry = entries![indexPath.row]
// date format.
let df = DateFormatter()
df.locale = Locale(identifier: "ja_JP")
df.timeZone = TimeZone.current
df.dateFormat = "MM/dd"
let dateStr = df.string(from: entry.publishedDate as Date)
cell.titleLabel.text = [dateStr,entry.title].joined(separator: " ")
cell.descriptionLabel.text = entry.contentSnippet
return cell
}
이상
꽤 엉망이지만 JSON을 얻고 내부 DB에 저장/표시 방향이 보였을까라는 느낌입니다.
Objective-C 때는 CoreData를 사용하고 있었습니다만, 데이터가 비대화할수록 보이는 퍼포먼스가 떨어지는 듯 어리석은 기억이 있습니다.
Realm을 사용해 얼마나 퍼포먼스에 차이가 나오는지, 지금부터 기대입니다.
참고로 한 기사
[Swift]ObjectMapper를 사용하여 Realm 모델에 JSON 매핑 - Qiita
정약이 Swift 용 ObjectMapper 읽어 보았다 - Qiita
Reference
이 문제에 관하여(Swift + Alamofire + ObjectMapper + Realm [Swift3 대응]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/SatoshiN21/items/d09f9e028c129ef567c1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)