在Swift中同时发送HTTP请求

在Swift中同时发送HTTP请求,swift,asynchronous,grand-central-dispatch,Swift,Asynchronous,Grand Central Dispatch,在启动我的应用程序时,我会使用UIGraphics执行一些http请求、一些繁重的http请求(下载一些图像)和一些繁重的任务(例如,使用两个UIGraphics为GMSMarker创建图标,并使用GraphicsContext执行其他操作)。这需要一些时间,所以我想同时完成所有这些任务。你能告诉我最好的方法吗? 开始时,我必须: 下载所有设备并将其写入本地数据库 下载并写入本地数据库所有地理围栏 下载并写入本地数据库所有用户 下载并写入本地数据库所有职位 下载设备、用户和地理围栏的图像 为设备

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

  • 下载所有设备并将其写入本地数据库
  • 下载并写入本地数据库所有地理围栏
  • 下载并写入本地数据库所有用户
  • 下载并写入本地数据库所有职位

  • 下载设备、用户和地理围栏的图像

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

  • 我的登录功能代码(它工作,但太慢):

    我不确定这是不是一个好主意,在这里发布所有类和对象的代码片段,希望你们能理解。 任何帮助都将不胜感激

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


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

    默认情况下,网络请求是异步的,所以您所要求的已经是预期的行为

    但是,您可以通过使用Promises库(例如)使您的生活简单得多

    示例用法可能如下所示:

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

    默认情况下,网络请求是异步的,因此您请求的内容已经达到预期的行为

    但是,您可以通过使用Promises库(例如)使您的生活简单得多

    示例用法可能如下所示:

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

    您的登录功能很慢,因为您正在下载和写入磁盘(正如您在问题中提到的)“所有”闭包中的数据(地理围栏、设备和/或位置)。此外,所有操作都在主线程中执行。永远不要在主线程中执行I/O(联网、写入磁盘),因为此线程主要用于UI更新。您应该使用GCD将昂贵的任务卸载到另一个线程

    另外,值得一提的是,写入磁盘是一个相对缓慢的操作,尤其是当您为正在下载的每个项目执行写入操作时

    我建议您只下载要显示的任何数据,然后使用DispatchQueue(GCD)中的异步任务在UI中显示数据后将下载的数据持久化到磁盘

    我不确定DB.geofenses.server.getAll()行对geofenses、设备和位置有何作用(关于如何处理网络或数据库获取),因此我无法就此向您提供建议。我可以给您的建议是,按照以下方式构造代码:

  • 当用户登录时,对DB(远程)进行验证,并防止有效登录。接下来转换到下一个视图控制器(不要执行所有逻辑),因为我可以看到您将太多的责任委托给了登录操作(对于登录按钮)
  • 从第二个视图控制器,使用
    .UserInitiated
    优先级,通过另一个线程上的网络调用异步获取数据(以快速获得结果)
  • 完成所有网络操作后,调用
    DispatchQueue.main.async{…}
    以在主线程中使用刚获得的数据异步更新UI
  • 显示下载的数据后,可以将其持久化到本地数据库,最好使用另一个DispatchQueue异步任务
  • 如果我上面说的任何话对你没有任何意义,请阅读AppCoda关于GCD的文章和RayWenderlich关于GCD的文章。他们将为您提供有关iOS中GCD的基本知识。完成后,请返回并尝试按照我上面建议的方式构造代码


    我希望这有帮助

    您的登录功能很慢,因为您正在下载和写入磁盘(正如您在问题中提到的)闭包中的“所有”数据(地理围栏、设备和/或位置)。此外,所有操作都在主线程中执行。永远不要在主线程中执行I/O(联网、写入磁盘),因为此线程主要用于UI更新。您应该使用GCD将昂贵的任务卸载到另一个线程

    另外,值得一提的是,写入磁盘是一个相对缓慢的操作,尤其是当您为正在下载的每个项目执行写入操作时

    我建议您只下载要显示的任何数据,然后使用DispatchQueue(GCD)中的异步任务在UI中显示数据后将下载的数据持久化到磁盘

    我不确定DB.geofenses.server.getAll()行对geofenses、设备和位置有何作用(关于如何处理网络或数据库获取),因此我无法就此向您提供建议。我可以给您的建议是,按照以下方式构造代码:

  • 当用户登录时,对DB(远程)进行验证,并防止有效登录。接下来转换到下一个视图控制器(不要执行所有逻辑),因为我可以看到您将太多的责任委托给了登录操作(对于登录按钮)
  • 从第二个视图控制器上,通过异步的网络调用获取数据