【问题标题】:Where to put network requests when app first starts应用程序首次启动时将网络请求放在哪里
【发布时间】:2018-07-02 03:27:01
【问题描述】:

当应用启动时,我需要做一些网络请求。例如,App 获取我的服务器公钥以运行安全的 restful 连接。如果它可以获得密钥,它会进行其他网络操作。我的问题是这些操作是嵌套的,所以一个完成,另一个开始,但如果其中一个有问题,我需要显示一条消息。我有 AppDelegate 类和 SplashViewController,我可以在其中执行这些操作。我不确定这样做时速度方面的最佳方法是什么;

1-) 在 AppDelegate 和通知中启动操作,如果有错误,通知 splashviewcontroller 并显示消息。

2-)在 SplashViewController 类中启动操作。

3-)在打开 SplashViewController 之前等待所有网络操作完成(我不确定是否可以在 AppDelegate 类中显示错误消息)

我在 AppDelegate 运行的示例代码;

 APIClient.checkCMS { (result) in
  switch result{
    case .error(let error):
        print(error)
        //Notify SplashViewController?
    case .success(let returnedObject):
        print(returnedObject)
        print("Devam")
               }
  }

【问题讨论】:

  • 我会选择数字 1。(假设您的网络代码将在某些服务中,而不是在应用程序委托中。)
  • 我还建议研究异步包装器,例如 PromiseKit;它会让这更整洁。
  • 我知道 PromiseKit 但这与我的问题无关。我的意思是我的问题是我无法决定将 Promisekit 或一些网络代码放在哪里.. Appdelegate 或 splash 类?
  • @EmreO。这取决于您的要求。当您的数据正在下载/阻止 UI 时,您会让用户在 SplashScreen 上等待吗?或者你会做一个异步请求并以空白状态(或缓存状态)继续应用程序。
  • @Hapeki 我会在任何情况下等待,但我想尽量减少等待时间。

标签: ios swift networking alamofire


【解决方案1】:

您甚至考虑在此处使用通知在视图控制器之间进行通信的事实可能是代码异味。我认为AppDelegate 的做法肯定是错误的。

我对您的应用做出了一些可能不正确的假设,即您使用的是故事板/xib,并且无论网络调用的状态如何,您的 SplashVC 都会在应用运行时被实例化并呈现(即应用程序不会挂起,直到知道网络调用的结果)。

在这种情况下,如果您从AppDelegate 拨打电话,您将使用NSNotificationCenter 来更新SplashVC。这似乎是个坏主意,因为它给设计带来了不必要的复杂性。如果您在代码中手动加载 VC,您可能可以想象AppDelegate 执行所有操作,但即便如此,您也可能不希望应用程序在网络调用完成之前不显示任何内容。

我的处理方式如下:

  1. (如果您还没有这样做)将所有网络请求封装到某种服务对象中。然后,您可以将依赖注入与单例范围一起使用(可能使用 Swinject 或其他类似库)。这将允许您从应用程序中所需的任何位置发出网络请求。

  2. 有一个默认的 VC(可能是 SplashVC,或其他一些根 VC),它首先加载并依赖从 1 注入网络服务

  3. 在 SplashVC 的 viewDidLoad 中进行调用。适当地处理错误,(通过显示警报,或通过呈现自定义模态 VC,或任何您喜欢的方式。这样可以避免在请求缓慢时让应用程序只显示黑屏)。

【讨论】:

  • 我有处理网络请求的 APIClient 类。实际上,我认为我们是同一方面的,但我无法清楚地表达我的观点。例如,SplashVC 打开之前的时间是 3 秒。如果我在 SplashVC 中启动所有请求,我会多等 3 秒,但如果我在 AppDelegate 启动它们,这意味着我会少获得 3 秒。如果我们来了,我为什么要使用通知是如果某些请求失败,我需要显示错误消息。
  • 当这些可以是静态方法时,为什么要使用单例来执行网络请求?例如。 ApiHandler.login(.....)
  • @Hapeki。一句话,测试。它是一个具有单例范围的依赖注入对象,而不是实际的单例 - 因此您可以创建一个不同的 DI 容器进行测试并注入一个虚假的网络服务进行测试。使用静态方法会让这更尴尬
  • @EmreO。如果你使用 Rx 或类似的,你可以从AppDelegate 开始请求,并通过订阅SplashVC 中的流来监听响应。但是您必须小心,以确保在您订阅之前不会错过回复。我不太确定 - (我的 RxSwift 有点生疏)但其他 Rx 库有“重播”方法,允许您访问订阅之前发生的事件 - 这可能在这里工作。
  • 不,我没有使用 Rx,只是使用原生 Swift :) @RichTolley
【解决方案2】:

通常,开发人员会创建一个虚假的启动画面。它看起来像飞溅,所以用户不会注意到任何区别。在控制器初始化程序(或viewDidLoad)上,您可以下载所有需要的数据,当一切完成后转到下一个控制器。更重要的是,您可以选择下一步去哪里(例如,如果用户之前登录过,他应该被重定向到主页)。

【讨论】:

  • 我已经这样做了,但是在应用程序出现 Splashcontroller 之前还有 3 秒的时间,所以我问如果在 appdelegate 中启动请求并在启动时等待它们会更好跨度>
  • 时差太小,人眼都看不到,对你没用。如果需要很长时间,您可以显示进度 HUD 以指示正在进行一些处理。这样做是通常的做法。
猜你喜欢
  • 2023-03-24
  • 2012-11-17
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多