Skip to content

Instantly share code, notes, and snippets.

@syou007
Created May 19, 2017 01:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save syou007/8b2aa1567c077eb24740a37a77ba4b32 to your computer and use it in GitHub Desktop.
Save syou007/8b2aa1567c077eb24740a37a77ba4b32 to your computer and use it in GitHub Desktop.
[2017年版]RxSwift + Alamofire + ObjectMapper + RealmのSwift実装について ref: http://qiita.com/syou007/items/8f27e7f0d03b9cfcff6c
github "ReactiveX/RxSwift"
github "realm/realm-cocoa"
github "Alamofire/Alamofire" ~> 4.4
github "Alamofire/AlamofireImage" ~> 3.1
github "Hearst-DD/ObjectMapper" ~> 2.2
github "tristanhimmelman/AlamofireObjectMapper" ~> 4.0
import RealmSwift
import ObjectMapper
class Area: Object, Mappable {
// エリア名
dynamic var name = ""
// エリアコード
dynamic var code = ""
required convenience init?(map: Map) {
self.init()
}
func mapping(map: Map) {
name <- map["name"]
code <- map["code"]
}
}
func mapping(map: Map) {
name <- map["name"]
}
func mapping(map: Map) {
date <- (map["date"], CustomDateFormatTransform(formatString: "yyyy-MM-dd'T'HH:mm:ss.SSSZ"))
}
import RealmSwift
import ObjectMapper
class Prefecture: Object, Mappable{
// 都道府県名
dynamic var name = ""
// [変更]エリアを複数形で定義
var areas = List<Area>()
required convenience init?(map: Map) {
self.init()
}
func mapping(map: Map) {
name <- map["name"]
// [変更]エリアを追加
area <- (map["areas"], ArrayTransform<Area>())
}
}
class ArrayTransform<T:RealmSwift.Object> : TransformType where T:Mappable {
typealias Object = List<T>
typealias JSON = Array<AnyObject>
let mapper = Mapper<T>()
func transformFromJSON(_ value: Any?) -> List<T>? {
let result = List<T>()
if let tempArr = value as! Array<AnyObject>? {
for entry in tempArr {
let mapper = Mapper<T>()
let model : T = mapper.map(JSON: entry as! [String : Any])!
result.append(model)
}
}
return result
}
func transformToJSON(_ value: Object?) -> JSON? {
var results = [AnyObject]()
if let value = value {
for obj in value {
let json = mapper.toJSON(obj)
results.append(json as AnyObject)
}
}
return results
}
}
func request(callback:([Prefecture])->()) {
Alamofire.request("http://localhost/api/pref.json").responseArray() { (response:
DataResponse<[Prefecture]>) in
switch response.result {
case .success(let prefectures):
// データ取得成功したの保存します。
let realm = try! Realm()
try! realm.write {
// 「update: true」のオプションに関しては今回は割愛します。
realm.add(prefectures)
}
callback(prefectures)
case .failure(let error):
// データ取得エラー
}
}
}
request() { (prefectures) in
print(prefectures)
}
// [変更] 戻り値を追加
func request() -> Observable<[Prefecture]> {
// [変更] Observableを返却
return Observable.create { (observer: AnyObserver<[Prefecture]>) in
Alamofire.request("http://localhost/api/pref.json").responseArray() { (response:
DataResponse<[Prefecture]>) in
switch response.result {
case .success(let prefectures):
// データ取得成功したの保存します。
let realm = try! Realm()
try! realm.write {
// 「update: true」のオプションに関しては今回は割愛します。
realm.add(prefectures)
}
// [変更] 通知の処理は「observer」に任せる。
observer.on(.next(prefectures))
observer.onCompleted()
case .failure(let error):
// データ取得エラー
// [変更] 通知の処理は「observer」に任せる。
observer.onError(error)
}
}
return Disposables.create()
}
}
request().subscribe(onNext: { (prefectures) in
print(prefectures)
}, onError: {...})
func request() -> Observable<[Prefecture]> {
return Observable.create { (observer: AnyObserver<[Prefecture]>) in
// [追加] キャッシュがある場合
if キャッシュがある場合 {
observable.on(.next(Prefecture.all()))
observable.onCompleted()
return Disposables.create()
}
Alamofire.request("http://localhost/api/pref.json").responseArray() { (response:
DataResponse<[Prefecture]>) in
switch response.result {
case .success(let prefectures):
// データ取得成功したの保存します。
let realm = try! Realm()
try! realm.write {
// [変更]エリアデータは自動的に消えないため、手動で削除する。
realm.delete(realm.objects(Area.self))
realm.add(prefectures, update: true)
}
observer.on(.next(prefectures))
observer.onCompleted()
case .failure(let error):
// データ取得エラー
observer.onError(error)
}
}
return Disposables.create()
}
}
import Alamofire
...
Alamofire.request("http://localhost/api/pref.json").responseJSON { response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
request().observeOn(MainScheduler.instance).subscribe(onNext: { (prefectures) in
// UIを変更する
}, onError: {...})
func createRequest(url:String, parameters: Parameters? = nil) -> Alamofire.DataRequest {
let manager = Alamofire.SessionManager.default
// タイムアウト
manager.session.configuration.timeoutIntervalForRequest = 300
return manager.request(url,
// メソッド
method:.get,
parameters: parameters,
encoding: JSONEncoding.default,
// 共通ヘッダー
headers: ["Accept": "application/json"]).validate()
}
// 使用例
createRequest(url:"http://localhost/api/pref.json").responseArray...
import AlamofireImage
// 省略
// ただ画像を表示する。
imageView.af_setImage(withURL: Url())
// 画像を表示できない場合に代替画像を入れたり、画像ロード後にリサイズしたりしたい場合
imageView.af_setImage(withURL: Url(), placeholderImage: UIImage(named: "DefaultImage"), completion: { (image) in
if let image = image.value {
// 表示後に何かしたい場合
}
})
import ObjectMapper
class Prefecture: Mappable{
// 都道府県名
dynamic var name = ""
required init?(map: Map) {}
// Mappable
func mapping(map: Map) {
name <- map["name"]
}
}
import Alamofire
import ObjectMapper
import AlamofireObjectMapper
...
Alamofire.request("http://localhost/api/pref.json").responseArray() { (response: DataResponse<[Prefecture]>) in
switch response.result {
case .success(let prefectures):
// データ取得成功([Prefectures]としてデータが取得できてます。)
print("Prefectures: \(prefectures)")
case .failure(let error):
// データ取得エラー
}
}
// [変更] responseArray->responseObjectに変更して[Prefecture]->Prefectureになっている。
Alamofire.request("http://localhost/api/pref.json").responseObject() { (response: DataResponse<Prefecture>) in
switch response.result {
case .success(let prefecture):
// データ取得成功
print("Prefecture: \(prefecture)")
case .failure(let error):
// データ取得エラー
}
}
Alamofire.request("http://localhost/api/pref.json").responseArray(keyPath: "pref") { (response: DataResponse<[Prefecture]>) in
switch response.result {
case .success(let prefectures):
// データ取得成功
print("Prefectures: \(prefectures)")
case .failure(let error):
// データ取得エラー
}
}
// [変更]RealmSwiftを追加する。
import RealmSwift
import ObjectMapper
// [変更]Objectクラスを継承する。
class Prefecture: Object, Mappable {
// 都道府県名
dynamic var name = ""
// [変更]この部分を以下のように変更する。
required convenience init?(map: Map) {
self.init()
}
// Mappable
func mapping(map: Map) {
name <- map["name"]
}
}
Alamofire.request("http://localhost/api/pref.json").responseArray() { (response: DataResponse<[Prefecture]>) in
switch response.result {
case .success(let prefectures):
// データ取得成功したの保存します。
let realm = try! Realm()
try! realm.write {
// 「update: true」のオプションに関しては今回は割愛します。
realm.add(prefectures)
}
case .failure(let error):
// データ取得エラー
}
}
{ "pref": [{
"id": 1,
"name": "北海道",
"areas": [
{
"name": "札幌",
"code": "sapporo"
},
{
"name": "函館",
"code": "hakodate"
}
]
},
{
...
}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment