【问题标题】:Why does my UITableView only show the list of available MGLOfflinePacks after I leave the current view controller and return to it?为什么我的 UITableView 在我离开当前视图控制器并返回它之后只显示可用 MGLOfflinePacks 的列表?
【发布时间】:2017-01-05 05:20:17
【问题描述】:

我正在使用 Mapbox-iOS-SDK 3.3.7 和 Swift 3 来开发一项功能,让用户可以下载地图以供离线使用。初始视图将有一个 UITableView,它将提供所有先前下载的 MGLOfflinePacks 的列表。我已尽力将 Objective-C example that Mapbox provides 移植到 Swift 3 以管理离线包。

不幸的是,我遇到了一个问题,即最初显示表格时没有出现脱机包。但是,如果我将另一个控制器推到 NavigationController 上,或者离开并返回 UITableView,脱机包列表将按预期显示。

我相信我的 Notification 观察者和 KVO 是根据 the documentation 正确设置的,但无论我尝试什么,tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) 总是返回 0,直到我离开控制器并返回,大概是因为 MGLOfflineStorage.shared().packs当代码被触发检查时返回 nil。

以下是我使用的代码的相关部分,这些代码是从上述 Obj-C 示例中移植而来的:

import Mapbox

class OfflineMapTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // observers for offline pack loading
        MGLOfflineStorage.shared().addObserver(self, forKeyPath: "paths", options: .initial, context: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(offlinePackProgressDidChange), name: NSNotification.Name.MGLOfflinePackProgressChanged, object: nil)
    }

    deinit {
        MGLOfflineStorage.shared().removeObserver(self, forKeyPath: "paths")
        NotificationCenter.default.removeObserver(self)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

        guard let change = change else { return }

        if keyPath == "paths" {
            if let changeKind = change[NSKeyValueChangeKey.kindKey] as? UInt,
                let kind = NSKeyValueChange(rawValue: changeKind) {

                var indexPaths: [IndexPath] = []

                if let indexes = change[NSKeyValueChangeKey.indexesKey] as? NSIndexSet {
                    if indexes.count > 0 {
                        indexes.enumerate({ (index, stop) in
                            indexPaths.append(IndexPath(row: index, section: 0))
                        })
                    }
                }

                switch kind {
                case NSKeyValueChange.insertion:
                    tableView.insertRows(at: indexPaths, with: .automatic)
                    break

                case NSKeyValueChange.removal:
                    tableView.deleteRows(at: indexPaths, with: .automatic)
                    break

                case NSKeyValueChange.replacement:
                    tableView.reloadRows(at: indexPaths, with: .automatic)
                    break

                default:
                    tableView.reloadData()

                    if let packs = MGLOfflineStorage.shared().packs {
                        for pack in packs {
                            if pack.state == .unknown {
                                pack.requestProgress()
                            }
                        }
                    }

                    break
                }
            }
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }

    func offlinePackProgressDidChange(notification: NSNotification) {
        guard let pack = notification.object as? MGLOfflinePack else { return }

        guard let index = MGLOfflineStorage.shared().packs?.index(of: pack) else { return }

        let indexPath: IndexPath = IndexPath(row: index, section: 0)

        if let cell = tableView.cellForRow(at: indexPath) {
            updateTableViewCell(cell, atIndexPath: indexPath, forPack: pack)
        }
    }

    // MARK: - Table view data source

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let packs = MGLOfflineStorage.shared().packs {
            return packs.count
        } else {
            return 0
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "idCell", for: indexPath)

        // Configure the cell...

        if let pack = MGLOfflineStorage.shared().packs?[indexPath.row] {
            updateTableViewCell(cell, atIndexPath: indexPath, forPack: pack)
        }

        return cell
    }

    func updateTableViewCell(_ cell: UITableViewCell, atIndexPath indexPath: IndexPath, forPack pack: MGLOfflinePack) {

        if let userInfo = NSKeyedUnarchiver.unarchiveObject(with: pack.context) as? [String: String] {
            if let name = userInfo["name"] {
                cell.textLabel?.text = name
            }
        }
    }

}

谁知道为什么离线包列表只在我离开然后返回视图控制器时出现?

【问题讨论】:

  • 'default' switch case 语句是否被调用过? MGLOfflineStorage.shared().packs 更新后应立即调用 tableView.reloadData()。
  • @RemyCilia 是的,调用了“默认”开关,但这很奇怪,因为MGOfflineStorage.shared().packs 在实际上应该返回可用包时返回 nil。只有当我返回此控制器时,该属性才会返回可用的包。

标签: ios mapbox mapbox-gl


【解决方案1】:

尝试将forKeyPath: "paths" 更改为forKeyPath: "packs"

MGLOfflineStorage 属性的名称是 packs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 2015-10-15
    • 1970-01-01
    相关资源
    最近更新 更多