RAC4を使用してサーバーから都市オブジェクトのリストを取得し、JSONとして戻すアプリケーションを開発しています。私は、各都市とその適切なプロパティをCityオブジェクトとして格納することによって応答を処理します。次に、各CityをCityViewModel型にマップし、[CityViewModel]型の配列をMutablePropertyとして格納します。ここから各都市がtableViewCellにファイルされ、名前を付けて表示され、progressBarを使用してセル内にダウンロードされます。タップすると、都市番号(都市ID)をパラメータとして使用して画像を含む大きな.zipファイルをダウンロードする別のサーバーリクエストがトリガーされます。RAC MutablePropertyプロデューサがイベントをサブスクライバに送信していない
ここでの目標は、進行状況のライブアップデートで進行状況バーをアニメーション化することです。タップすると、セルはdownloadCityData(nid: Int)
関数を呼び出し、すべてをオフにします。
都市のプロパティが更新されている間に、都市MutableProperty<[CityViewModel]>
は、DataViewModel
オブジェクトの外に変更のリスナーであることを通知していません。 (この場合DetailViewController
ある)
のViewController:
class DetailViewController: UIViewController {
@IBOutlet weak var cityTableView: UITableView!
private var bindingHelper: TableViewBindingHelper<CityViewModel>!
var viewModel: DetailViewModel?
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel = DetailViewModel()
self.viewModel!.cities.producer
.startOn(UIScheduler())
.startWithNext{ x in
/// this doesn't hear any changes as progress updates
}
bindingHelper = TableViewBindingHelper(tableView: cityTableView, sourceSignal: self.viewModel!.cities.producer, nibName: "CityCell")
}
}
ビューモデル:
class DetailViewModel: NSObject {
var dataManager: DataManager
let cities = MutableProperty<[CityViewModel]>([CityViewModel]())
override init() {
self.dataManager = DataManager()
super.init()
self.dataManager.progressMarker.producer
.observeOn(UIScheduler())
.startWithNext{ [weak self] (nid, progress) in
self!.cities.value = (self!.cities.value.map{ city in
if city.nid.value == nid {
print(nid, progress)
city.downloading.value = true
city.progress.value = progress
}
return city
})
}
}
func downloadCityData(nid: Int) -> SignalProducer<(JSON?, Float), NSError> {
return dataManager.getCityData(nid)
.on(next: { (json, progress) in
/// download complete
print("download complete")
self.cities.value = (self.cities.value.map{ city in
if city.nid.value == nid {
city.downloading.value = false
city.downloadedBool.value = true
city.upToDate.value = true
}
return city
})
})
}
}
データマネージャー:
class DataManager: NSObject {
private let restClient = RestClient()
let progressMarker = MutableProperty<(Int, Float)>(0, 0)
override init() {
super.init()
}
func getCityData(nid: Int) -> SignalProducer<(JSON?, Float), NSError> {
return restClient.fetchCityData(nid)
.filter{ (fileName, progress) in
self.progressMarker.value = (nid, progress)
return fileName.characters.count > 0
}
.flatMap(FlattenStrategy.Latest, transform: unzipCityData)
.flatMap(FlattenStrategy.Latest, transform: unpackCityData)
}
}
がCityViewModel:
class CityViewModel: NSObject {
private let city: City
let name: ConstantProperty<String>
let nid: ConstantProperty<Int>
let progress: MutableProperty<Float>
let downloading: MutableProperty<Bool>
let downloadedBool: MutableProperty<Bool>
let downloadedString: MutableProperty<String>
let upToDate: MutableProperty<Bool>
init(city: City) {
self.city = city
name = ConstantProperty(city.name)
nid = ConstantProperty(city.nid)
progress = MutableProperty(city.progress)
downloading = MutableProperty(city.downloading)
downloadedBool = MutableProperty(city.downloaded)
downloadedString = MutableProperty(city.downloaded ? "downloaded" : "download now")
upToDate = MutableProperty(city.upToDate)
super.init()
}
}
市:
struct City {
var name: String
var nid: Int
var timestamp: Int
var progress: Float
var downloading: Bool
var downloaded: Bool
var upToDate: Bool
init() {
name = ""
nid = 0
timestamp = 0
progress = 0
downloading = false
downloaded = false
upToDate = false
}
}
私が推測する部分的な答え。 'TableViewBindingHelper'クラス内で何が問題になっているのかを正確にピンポイントすることは素晴らしいでしょう。 –