前回(Vol1)はこちら
http://qiita.com/nakadoribooks/items/c5f53071abdfafd47d4f
javascript実装はこちら
http://qiita.com/nakadoribooks/items/f7f48197d6d5723a96d5
成果物
https://github.com/nakadoribooks/CalilClient-ios/releases/tag/vol2
ActionCreator リファクタリング
- ActionCreator 内でのDispatchしない
ライブラリ取り込み
Podfile
use_frameworks!
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
target 'CalilClient' do
pod 'ReSwift'
pod "PromiseKit", "~> 4.0"
pod 'PromiseKit/Alamofire'
end
PromiseKitを使います
https://github.com/mxcl/PromiseKit
ActionCreator
ActionCreator.swift
static func loadLibraries(prefName:String="秋田県")-> Promise<Action>{
return Promise { fulfill, reject in
let parameters: Parameters = ["appkey": Config.API_KEY, "pref":prefName, "format":"json", "callback":""]
Alamofire.request(Config.API_LIBRARY, parameters: parameters).responseJSON().then { responseAny -> Void in
guard let json = responseAny as? [NSDictionary] else{
// 〜 略 〜
let failAction = LibraryListFailLoadAction()
fulfill(failAction)
return
}
print("ok json")
let results = Library.createList(list: json)
let loadedAction = LibraryListLoadedAction(libraryList: results)
fulfill(loadedAction)
}.catch { error in
let failAction = LibraryListFailLoadAction()
fulfill(failAction)
}
}
}
static func loadLibrariesAction()->Action{
return LibraryListLoadAction()
}
変更前
// ActionCreator interface
static func loadLibraries(prefName:String="秋田県")->Action
// 使う側 (View)
let loadAction = ActionCreator.loadLibraries()
mainStore.dispatch(loadAction)
変更後
// ActionCreator interface
static func loadLibraries(prefName:String="秋田県")-> Promise<Action>
static func loadLibrariesAction()->Action
// 使う側 (View)
ActionCreator.loadLibraries().then { (action) -> Void in
mainStore.dispatch(action)
}
let loadAction = ActionCreator.loadLibrariesAction()
mainStore.dispatch(loadAction)
たぶんこっちの方が好ましい。
※ 追記 AsyncActionCreator 使用バージョン
Webの方
http://qiita.com/nakadoribooks/items/f7f48197d6d5723a96d5
で redux-thunk のオススメコメントいただいたので、こっちもインタフェース揃える。
AsyncActionCreator
Reswiftの中に入ってる。
こいつが dispatch に渡せる
typealias AsyncActionCreator = (
_ state: State,
_ store: Store,
_ actionCreatorCallback: @escaping ((ActionCreator) -> Void)
) -> Void
mainStore.dispatch(AsyncActionCreator)
成果物
https://github.com/nakadoribooks/CalilClient-ios/releases/tag/vol2.5
準備
特になし。
ActionCreator
ActionCreator.swift
import ReSwift
import Alamofire
import PromiseKit
public enum ActionCreatorError: Error {
case unknown
case json
}
struct ActionCreator{
static func loadLibraries(prefName:String="秋田県")->Store<AppState>.AsyncActionCreator {
return { (state, store, callback) in
_loadLibraries(prefName: prefName).then(execute: { (action) -> Void in
callback({ (_, _) -> Action? in action })
}).catch(execute: { (error) in
let failAction = LibraryListFailLoadAction()
callback({ (_, _) -> Action? in failAction })
})
}
}
static func _loadLibraries(prefName:String="秋田県")-> Promise<Action>{
return Promise { fulfill, reject in
let parameters: Parameters = ["appkey": Config.API_KEY, "pref":prefName, "format":"json", "callback":""]
Alamofire.request(Config.API_LIBRARY, parameters: parameters).responseJSON().then { responseAny -> Void in
guard let json = responseAny as? [NSDictionary] else{
print("fail json")
reject(ActionCreatorError.json)
return
}
print("ok json")
let results = Library.createList(list: json)
let loadedAction = LibraryListLoadedAction(libraryList: results)
// 時間かかっているてい
DispatchQueue.global(qos: .default).async {
Thread.sleep(forTimeInterval: 1)
DispatchQueue.main.async {
fulfill(loadedAction)
}
}
}.catch { error in
reject(ActionCreatorError.unknown)
}
}
}
static func loadLibrariesAction()->Action{
return LibraryListLoadAction()
}
}
変更前
// ActionCreator interface
static func loadLibraries(prefName:String="秋田県")-> Promise<Action>
static func loadLibrariesAction()->Action
// 使う側 (View)
ActionCreator.loadLibraries().then { (action) -> Void in
mainStore.dispatch(action)
}
let loadAction = ActionCreator.loadLibrariesAction()
mainStore.dispatch(loadAction)
変更後
// ActionCreator interface
static func loadLibraries(prefName:String="秋田県")->Store<AppState>.AsyncActionCreator
static func loadLibrariesAction()->Action
// 使う側 (View)
mainStore.dispatch(ActionCreator.loadLibraries())
mainStore.dispatch(ActionCreator.loadLibrariesAction())
なるほど。