制作GMSMarkers时无法更新UI

时间:2017-09-24 20:24:50

标签: swift grand-central-dispatch gmsmapview

初始化GMSMarkers的功能:

func makeMarkers (progressHandler: ((String) -> Void)? = nil) {
    progressHandler?("Инициализируем маркеры...")
    for device in self.devices {
        progressHandler?("Инициализируем маркеры: для устройства \(device.name!)...")
        if let position = self.positions.findById(device.positionId) {
            if let marker = DeviceMarker(device, at: position) {
                self.deviceMarkers.append(marker)
            }
        }
    }
    for geofence in self.geofences {
        progressHandler?("Инициализируем маркеры: для геометки \(geofence.name!)...")
        if let marker = GeofenceMarker(geofence) {
            self.geofenceMarkers.append(marker)
        }
    }

    self.locationManager.requestLocation()

    progressHandler?("Инициализируем маркеры: для пользователя \(self.loggedUser.name!)...")
    if let userLocation = self.locationManager.location {
        self.userMarker = UserMarker(self.loggedUser, at: userLocation)
    } else {
        self.userMarker = UserMarker(self.loggedUser, at: CLLocation(latitude: 48, longitude: 44))
    }
    progressHandler?("Маркеры инициализированы...")
}

如您所见,我希望使用progressHandler告知用户此操作的进度。

但在执行该功能时,我看不到任何消息。 剪断我调用函数makeMarkers的地方:

                        ...
            DB.geofences.server.getAll() { geofences in
                self.statusLabel.text = "Получили геометки \(geofences.count)..."
                DB.devices.server.getAll() { devices in
                    self.statusLabel.text = "Получили устройства \(devices.count)..."
                    DB.positions.server.getAll() { positions in
                        self.statusLabel.text = "Получили позиции \(positions.count)..."

                        DB.devices.client.insert(devices)
                        self.statusLabel.text = "Записали устройства..."
                        DB.positions.client.insert(positions)
                        self.statusLabel.text = "Записали позиции..."
                        DB.geofences.client.insert(geofences)
                        self.statusLabel.text = "Записали геометки..."

                        MapManager.shared.makeMarkers() { status in
                            self.statusLabel.text = status
                        }
                        ...

如果我使用print()更改查看消息,将显示所有消息。 所以,问题是:为什么在执行我的函数期间阻止了UI更改以及如何摆脱它?

更新:当然,我在主线程中做了所有事情。

更新2:我正在调用我的函数更新的代码片段。在地图控制器显示之前我可以看到的最后一条消息是“Получилиустройства...”,这很奇怪,因为我确定我也能获得位置

1 个答案:

答案 0 :(得分:2)

嗯,这是因为UI更新发生在主线程中。但是当您更改标签的文本时,此更改不会立即发生。相反,所有UI更改都会被调度,并且只有在应用程序完成当前通过事件循环时才会呈现。

由于您在同一主循环中执行耗时的任务,因此它会被阻止,并且在这些任务完成并且函数返回之前不会发生更改。

您可以查看这些文章,详细了解事件循环的工作原理:Run LoopsMain event loop

我建议您将所有耗时的任务(例如数据库查询)移到后台线程,并在您真正想要更新UILabel时从那里调用主线程。