2017-09-24 66 views
2

该函数初始化GMSMarkers:无法更新UI

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此操作的进度。

但是在执行该功能期间,我看不到任何消息。 剪断其中I调用函数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 
         } 
         ... 

如果我使用打印改变视图消息()的所有消息将被显示。 所以,问题是:为什么在执行我的函数期间UI变化被阻止,以及如何摆脱?

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

更新2:我打电话更新我的功能的代码片段。我在地图控制器显示之前看到的最后一条消息是“Получилиустройства...”,这很奇怪,因为我敢肯定我的位置也是

+0

也许我误解了语法,但是你不是将你的progressHandler设置为零吗? – matiastofteby

+0

您是否试图强制它在主线程上运行,如 'DispatchQueue.main.async {self.statusLabel.text = status }''statusLabel'显示“Записалигеометки...”或不是? –

+0

@mathiastofteby:progressHandler设置为nil声明函数,这意味着默认值,当我调用我的函数progressHandler不是零。 – zzheads

回答

2

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

由于您在同一个主循环中执行耗时的任务,因此它会被阻塞,并且只有在这些任务完成并且函数返回时才会进行更改。

您可以检查这些文章以获取有关事件如何循环工作更详细的解释:Run LoopsMain event loop

我建议你将所有耗时的任务(如数据库查询)到后台线程,并调用主当你真的想更新你的UILabel时,从那里开始线程。