2

Function which initialize 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?("Маркеры инициализированы...")
}

As you can see I want inform user about progress of this operation using progressHandler.

But during execution of that function I can not see any of that messages. Snipped where I call function 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
                        }
                        ...

And if I change view messages using print() all messages will be shown. So, question is: why UI changes are blocked during execution of my function and how get rid of that?

UPDATE: Sure, I do everything in main thread.

UPDATE 2: Code snippet where I'm calling my function updated. Last message which I can see before map controller shows is "Получили устройства...", it is strange, because I'm sure I get positions as well

zzheads
  • 1,368
  • 5
  • 28
  • 57

1 Answers1

2

Well, that occurs because UI updates happen in the main thread. But when you change your label's text this change does not happen immediately. Instead, all UI changes get scheduled and only get rendered when the app finishes the current pass through the event loop.

Since you are performing time-consuming tasks in the same main loop, it becomes blocked and changes won't happen until those tasks are finished and your function returns.

You may check these articles to get more detailed explanation on how event loops work: Run Loops, Main event loop

I suggest you move all time-consuming tasks (such as database queries) to a background thread and call the main thread from there when you actually want to update your UILabel.

Artem M
  • 1,026
  • 14
  • 24