1

サーバーから都市オブジェクトのリストを取得し、JSON として返す RAC4 を使用したアプリを開発しています。各都市とその適切なプロパティを City オブジェクトとして格納することで、応答を処理します。次に、各 City を CityViewModel 型にマップし、[CityViewModel] 型の配列を MutableProperty として格納します。ここから、各都市が tableViewCell にファイルされ、セル内に名前とダウンロードの進行状況バーを使用して表示されます。タップすると、セルは都市の nid (都市 ID) をパラメーターとして使用して別のサーバー要求をトリガーし、画像などを含む大きな .zip ファイルをダウンロードします。

ここでの目標は、進行状況のライブ更新でプログレス バーをアニメーション化することです。タップすると、セルはすべてを開始するdownloadCityData(nid: Int)関数を呼び出します。

問題は、都市のプロパティが更新されている間、都市がオブジェクトMutableProperty<[CityViewModel]>の外部で変更をリスナーに通知していないことです。DataViewModel(この場合はDetailViewController)

ビューコントローラー:

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)
    }
}

シティビューモデル:

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
    }   
}
4

1 に答える 1

1

Colin Eberhardt の TableViewBindingHelperを使用しているようです。ビューモデルの信号をリッスンして観察するViewControllerの機能を奪っているようです。以前にも、このヘルパー クラスを使用して問題が発生しました。

于 2016-06-01T19:29:31.953 に答える