swift - 在 Swift 中同时发出 HTTP 请求

标签 swift asynchronous grand-central-dispatch

在启动我的应用程序时,我会执行一些 http 请求、一些繁重的 http 请求(下载一些图像)和一些使用 UIGraphics 的繁重任务(例如从两个 UIImages 为 GMSMarker 执行图标以及使用 GraphicsContext 执行其他操作)。这需要一些时间,所以我想同时完成所有这些任务。你能告诉我最好的方法吗? 一开始我必须:

  1. 下载所有设备并写入本地数据库
  2. 下载所有地理围栏并写入本地数据库
  3. 下载所有用户并写入本地数据库
  4. 下载所有位置并写入本地数据库

  5. 为设备、用户和地理围栏下载图像

  6. 为设备、用户和地理围栏设置 GMSMarkers(在该对象的图像可用后 - 用于设置标记图标)

我的登录函数的代码(可以运行,但是太慢了):

func loginPressed(_ sender: UIButton) {

    guard
        let username = self.usernameTextField.text,
        let password = self.passwordTextField.text,
        !username.isEmpty,
        !password.isEmpty
        else {
            return
    }

    self.loginButton.isEnabled = false
    self.activityIndicator.startAnimating()

    WebService.shared.connect(email: username, password: password) { error, loggedUser in
        guard
            error == nil,
            let loggedUser = loggedUser
            else {
                self.showAlert(title: "Ошибка подключения", message: error?.localizedDescription ?? "", style: .alert)
                self.activityIndicator.stopAnimating()
                self.loginButton.isEnabled = true
                return
        }
        DB.users.client.insert(loggedUser)


        print("Start loading user photo...")
        loggedUser.loadPhoto() { image in
            if let image = image {
                loggedUser.photo = UIImageJPEGRepresentation(image, 0.0)
            }
            print("User photo loaded...")
            loggedUser.marker = UserMarker(loggedUser, at: CLLocation(latitude: 48.7193900, longitude: 44.50183))
            DB.users.client.modify(loggedUser)
        }

        DB.geofences.server.getAll() { geofences in
            DB.devices.server.getAll() { devices in
                DB.positions.server.getAll() { positions in

                    for device in devices {
                        device.loadPhoto() { image in
                            if let image = image {
                                device.photo = UIImageJPEGRepresentation(image, 0.0)
                            }
                            if let position = positions.findById(device.positionId) {
                                device.marker = DeviceMarker(device, at: position)
                            }
                            device.attributes.battery = device.lastKnownBattery(in: positions)
                        }
                    }

                    geofences.forEach({$0.marker = GeofenceMarker($0)})
                    DB.geofences.client.updateAddress(geofences) { geofences in
                        if DEBUG_LOGS {
                            print("Geofences with updated addresses: ")
                            geofences.forEach({print("\($0.name), \($0.address ?? "")")})
                        }

                        DB.devices.client.insert(devices)
                        DB.geofences.client.insert(geofences)
                        DB.positions.client.insert(positions)

                        self.activityIndicator.stopAnimating()

                        WebService.shared.addObserver(DefaultObserver.shared)
                        self.performSegue(withIdentifier: "toMapController", sender: self)
                    }
                }
            }
        }
    }
}

不确定在此处张贴所有类和对象的代码片段是否是个好主意,希望您能理解。 任何帮助,将不胜感激。

附言如果您想知道什么是 DB,它是数据库,它由两部分组成 - 每组对象的服务器端和客户端,因此第一个任务是从服务器获取所有对象并将它们写入内存(在客户端数据库中)

附言我已将登录时的“下载所有内容”逻辑更改为“立即下载我需要的所有内容,稍后再下载其余内容”。因此,现在在我获得所有设备、地理围栏和位置后,我正在对 MapController 执行 segue,在其上显示所有这些对象。登录后,我将显示带有默认 iconView 的 deviceMarkers (GMSMarker)。所以问题是 - 在显示包含所有对象的 map 之后,我可以开始在后台下载设备照片,然后用这些照片刷新标记(当然是在主线程中)吗?

最佳答案

默认情况下网络请求是异步的,因此您所请求的已经具有预期的行为。

但是,您可以使用 Promises 库(例如 then)让您的生活变得更加简单。 .

示例用法可能如下所示:

login(email: "foo@bar.com", password: "pa$$w0rd")
    .whenAll(syncDevices(), syncGeofences(), syncUsers(), syncPositions(), syncImages())
    .onError { err in
       // process error
    }
    .finally {
       // update UI
    }

关于swift - 在 Swift 中同时发出 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46162049/

相关文章:

ios - NSOperation 的 qualityOfService 是否可以低于 NSOperationQueue?

swift - SpriteKit的didBeginContact无法调用

arrays - 替换解析中的对象

swift - 将数据写入 Firebase 不起作用 - 无法将类型 'user' 的值转换为预期参数类型 'AnyObject?'

Node.js 异步映射限制和内存

ios - 核心数据和数据完整性 : read operations vs write operations. 如何保护?

swift - 为什么 string.contains ("text") 不适用于 swift 5 中的字符串?

python requests-futures 慢 - 线程不正确?

python - 新的 python async 和 await 关键字

iphone - dispatch_group_wait 与 GCD