在 swift 中按串行顺序同步多个 Web 服务调用

2023-11-21

我点击 Web 服务 URL 10 次并得到响应。我在用Alamofire and SwiftyJSON。这是我的控制器代码

class ViewController: UIViewController {

    let dispatchGroup = DispatchGroup()

    var weatherServiceURL = "http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"

    override func viewDidLoad() {
        super.viewDidLoad()
        start()
    }

    func start() {
        weatherService()
        dispatchGroup.notify(queue: .main) {
            print("All services complete")
        }
    }

    func weatherService() {
        for i in 1...10 {
            dispatchGroup.enter()
            APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
                if let error = error {
                    print(error.localizedDescription)
                    return
                }
                guard let response = response else { return }
                print("\n\(response) \n\(count) response\n")
                self.dispatchGroup.leave()
            }
        }
    }
}

这是我的服务处理程序类代码

class APIManager: NSObject {

    class func apiGet(serviceName:String,parameters: [String:Any]?, completionHandler: @escaping (JSON?, NSError?, Int) -> ()) {
        Alamofire.request(serviceName, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in

            switch(response.result) {
            case .success(_):
                if let data = response.result.value{
                    let json = JSON(data)
                    completionHandler(json,nil, parameters!["counter"] as! Int)
                }
                break

            case .failure(_):
                completionHandler(nil,response.result.error as NSError?, parameters!["counter"] as! Int)
                break
            }
        }
    }
}

我发送一个带有 for 循环索引的计数器键,只是为了跟踪哪个索引返回的响应。但响应并不是按顺序出现的。我们可以在第二次和第一次响应之前期待第三次响应。这是因为 API 调用使用APIManager.apiGet函数调用是异步的并且正在转义,因此继续 for 循环。

我还使用了dispatchQueue

let dispatchQueue = DispatchQueue(label: "com.test.Queue", qos: .userInteractive)

并将函数转换为:

func weatherService() {
    for i in 1...10 {
        dispatchGroup.enter()
        dispatchQueue.async {
            APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
                if let error = error {
                    print(error.localizedDescription)
                    return
                }
                guard let response = response else { return }
                print("\n\(response) \n\(count) response\n")
                self.dispatchGroup.leave()
            }
        }
    }
}

结果与服务调用代码是异步的相同。如果我们做

dispatchQueue.sync {
   //service call 
}

那么我们也不会按串行顺序获得响应,因为异步和调度队列中的网络调用假设任务已完成。

条件是仅以异步方式访问服务而不冻结 UI。如果我以同步方式点击服务,那么我就会得到我想要的结果。但阻塞主线程是完全不可接受的。

我可以使用数组或一些全局布尔变量来管理这个东西,但我不想使用它们。有没有其他方法可以按调用的顺序获得响应?任何帮助或提示表示赞赏。


解决方案:使用DispatchSemaphores and a DispatchQueue

我决定将所有内容包装在调度队列中并在其中使用信号量,而不是保存闭包

//Create a dispatch queue 
let dispatchQueue = DispatchQueue(label: "myQueue", qos: .background)

//Create a semaphore
let semaphore = DispatchSemaphore(value: 0)

func weatherService() {

    dispatchQueue.async {
        for i in 1...10 {
            APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
                if let error = error {
                    print(error.localizedDescription)
                    self.semaphore.signal()
                    return
                }
                guard let response = response else { 
                    self.semaphore.signal()
                    return 
                }

                print("\(count) ")

                //Check by index, the last service in this case
                if i == 10 {
                    print("Services Completed")
                } else {
                    print("An error occurred")
                }

                // Signals that the 'current' API request has completed
                self.semaphore.signal()
            }

            // Wait until the previous API request completes
            self.semaphore.wait()
        }
    }
    print("Start Fetching")
}

Output is this always

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 swift 中按串行顺序同步多个 Web 服务调用 的相关文章

  • GCD 和线程

    我想了解一些有关 GCD 和线程的知识 我的视图控制器中有一个 for 循环 它要求我的模型执行一些异步网络请求 因此 如果循环运行 5 次 模型将发出 5 个网络请求 考虑到我正在使用 NSURLConnection 的 sendAsyn
  • 在 Flurry 中记录比错误 ID 更多信息的方法?

    我目前使用 iOS 版 Flurry 5 4 0 我担心在方法方面是否能够记录更多信息 而不仅仅是错误 ID void logError NSString errorID message NSString message error NSE
  • 从 UTC 转换为本地时区给出错误结果

    背景我需要将格式为 HH mm 的时间字符串从 UTC 转换为本地时区 例如 如果 UTC 时间为 09 00 则当地时间 斯德哥尔摩 欧洲 应提前两个小时 Problem当我将 09 00 UTC 转换为斯德哥尔摩 欧洲时间时 我得到 1
  • 如何通过填充 NSDictionary 以 JSON 格式发送 UIImage

    我正在尝试使用 JSON 将数据发送到服务器 我可以使用我的对象和关键参数创建 NSDictionary 但我想发送我的图片 图片是UIImage NSDictionary mainJSON NSDictionary dictionaryW
  • 在哪里实现 Swift 协议?

    在 Swift 中实现协议一致性时 我有两个选择 具有相同的最终结果 在类中实现协议 也就是说 在类定义的顶部声明一致性 并将实现放在类体内 或者 在扩展中实现协议 也就是说 完全在类之外编写符合协议的代码 这是一个例子 public cl
  • Cocos2D复杂动画[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 Cocos2D 将我的游戏从 Flash 移植到 iOS 我现在有一个工作版本 我很高兴我
  • 有什么方法可以让dispatch_queue_t在单线程中工作吗?

    这是我的代码 interface MyObject property nonatomic dispatch queue t queue end implementation MyObject NSThread check id init s
  • iOS 中的内存泄漏,AVPlayer 永远不会被释放

    我使用了 AVPlayerDemo 示例苹果文档 https developer apple com library ios samplecode AVPlayerDemo Introduction Intro html并在其上编写了我自己
  • iPad 2 检测

    由于我没有 iPad 2 因此我需要知道调用 UIDevice currentDevice model 时它返回什么 我以为它只返回 iPad 但看来我错了 有人可以告诉我吗 Thanks 检查是否有带摄像头的 iPad BOOL isIP
  • 我如何在 viewDidLoad 中执行 UIView animateWithDuration ? IOS 7

    我在 viewDidAppear 中尝试这个 但我有一秒钟的延迟 我能做什么 在 viewDidLoad 中工作 void viewDidAppear BOOL animated fullRotation CABasicAnimation
  • 是否可以在 Swift 中交错 WebView 和 CALayerViews

    我有一个充当多个 CAShapeLayers 容器的视图 它们包含在屏幕上形成组合的贝塞尔曲线 用户可以通过不同的方式管理线宽 颜色 形状填充 不透明度等 我想通过占据相同容器的 WebView 引入文本 诀窍是 理想情况下我希望能够控制每
  • 在 SKScene 上运行 SKTransition 是否会破坏原始 SKScene?

    在 SKScene 上运行 SKTransition 是否会破坏原始 SKScene 例如 SKTransition reveal SKTransition revealWithDirection SKTransitionDirection
  • iOS:加载时的设备方向

    似乎当我的应用程序加载时 它不知道其当前方向 UIInterfaceOrientation orientation UIDevice currentDevice orientation if orientation UIDeviceOrie
  • 在视图控制器中获取 applicationDidFinishLaunching 调用。解析尚未初始化

    我正在尝试从 Parse 加载数据Initial View 控制器 问题是 Parse 在我的中初始化AppDelegate s didFinishLaunching所以我需要等到它被调用后再尝试从 Parse 加载数据 在我的视图控制器中
  • iOS 自定义滑块删除两端的最小和最大空间

    我正在尝试使用自定义滑块 class MySlider UISlider override func trackRect forBounds bounds CGRect gt CGRect let customBounds CGRect o
  • 如何使用 iOS 可达性

    我正在开发一个使用网络的 iPhone 应用程序 iPhone 通过 HTTP 请求与我的服务器通信 并且应该可以在 WiFi 和 3G 上运行 我目前使用NSURLConnection initWithRequest向我的服务器发送异步请
  • Flutter - 选择 TextFormField 时键盘不显示

    我目前遇到一个问题 当我选择任何一个时 键盘不会出现TextFormFielda 内的小部件Form小部件 这是表单的代码 位于我的内部CreateAccountForm有状态的小部件 import package flutter mate
  • 使用远程图像创建 MSSticker

    我正在尝试找出使用网络上托管的图像创建 MSStickers 的方法 我可以使用本地图像创建 MSStickers 例如 NSString imagePath NSBundle mainBundle pathForResource imag
  • 如何在 iOS 中通过 Twitter API 获取用户电子邮件地址?

    我尝试了多个 SDK 但无法从任何资源获取电子邮件 ID 我努力了FHSTwitterEngine为此目的 但我没有得到解决方案 FHSTwitterEngine twitterEngine FHSTwitterEngine sharedE
  • 使用 NSString 进行 UTF8 解码

    我是 Objective C 新手 尝试使用以下示例将格式错误的 UTF8 编码 NSString 转换为格式良好的字符串苹果文档 http developer apple com library mac documentation Coc

随机推荐

  • 垂直对齐 ggplot2 绘图

    代码位于https gist github com low decarie 5886616可以生成双树状图平铺图 Dual dendogram tile plot as matrix USArrests main 美国逮捕 问题 将垂直树状
  • C# 如何获取来电显示?

    我想使用 56K 调制解调器获取拨打家庭电话的电话号码 有没有办法用 C 来实现这一点 并非所有调制解调器都支持主叫号码 对于那些这样做的人 制造商之间的实施方式有所不同 呼叫者 ID 通过串行数据传递 因此您必须使用TAPI库 或使用 W
  • 如果我想要空插值(分段常数),那么 numpy.interp 的最佳替代品是什么?

    numpy interp很方便 也比较快捷 在某些情况下 我想将其输出与非插值变体进行比较 其中稀疏值被传播 在 更密集 的输出中 并且结果是稀疏输入之间的分段常数 我想要的函数也可以称为 稀疏 gt 密集 转换器 它复制最新的稀疏值 直到
  • React Native 和 THREE.js(WebGL 库)集成

    我正在开发一个使用 React Web 和 React Native 的项目 我已经实现了一个 React Web 组件 它允许您从 OBJ MTL 和图像文件加载 3D 模型 加载模型后您可以对其进行编辑 在其上附加 3D 标签等内容 最
  • 期望有根视图控制器控制台的应用程序

    当我运行我的应用程序时 我在控制台中收到一条消息 2011 11 16 19 17 41 292 Juice 8674 707 应用程序预计在应用程序启动结束时有一个根视图控制器 我听别人说这与方法有关didFinishLaunchingW
  • 我可以在卫星程序集中合并本地资源吗?

    我有很多本地资源文件 Controls App LocalResources SomeControl ascx resx Pages App LocalResources SomePage aspx resx 等 我想添加另一种语言 但我不
  • Windows 窗体:检测焦点控件的变化

    我正在 Windows 窗体应用程序中实现复制粘贴 当用户更改应用程序中的焦点元素时 我需要启用 禁用这两个操作的栏按钮 我可以使用这样的方法找到当前的焦点控件 http www syncfusion com FAQ windowsform
  • Delphi:确定泛型的实际类型?

    有什么方法可以确定作为参数传递给方法的变量的类型吗 考虑一下这个类 TSomeClass class procedure AddToList
  • 如何检查 mysqli_query 是否删除了任何行[重复]

    这个问题在这里已经有答案了 我创建了从数据库中删除一些数据的函数 这是其中的一部分 mysqli query con DELETE FROM appsdata WHERE ownerID 123 但我想检查删除了多少行 mysql quer
  • 通过查找/替换 (Ctrl+F) 删除 Eclipse 代码编辑器中的空行

    我想通过 Eclipse 代码编辑器中的查找 替换方法从代码中删除所有空白行 我使用了正则表达式 n s n找到所有空白行但出现错误 Incompatible line delimiter near index 55110 用任何字符串替换
  • 如何获取特定类型类实例的多态函数的类型?

    例如 输入 t ap在 GHCi 中给出结果 ap Monad m gt m a gt b gt m a gt m b 如果我已经知道我要使用的 Monad 实例是 gt r 如何查询类型ap对于那个特定的例子 As 激光烟说作为评论你可以
  • 使用 Eclipse/Tomcat 自动将第 3 方 jar 添加到 WEB-INF/lib [重复]

    这个问题在这里已经有答案了 我在 Eclipse 上设置了一个动态 Web 项目 并使用 Tomcat 7 作为我的 Web 服务器 它似乎不会自动将我添加到构建路径上的库中的第 3 方 JAR 放入 WEB INF lib 文件夹中 有没
  • 创建 IE 插件

    我正在寻找为 IE 8 或 9 制作插件的教程 你能给我提供资源吗 拜托 为了和平和其他一切 我已经知道我可以制作 FF 或 Chrome 插件 我want制作一个 IE 插件 Thanks 你见过吗这个网站
  • 如何使 C# 枚举与数据库中的表保持同步

    这是一个稍微简化的示例 我对其进行了更改以隐藏实际代码 我有一个数据库驱动的应用程序和一个单独开发的小工具 旨在与该应用程序一起使用 有一个表定义了枚举 但它可能会随着时间的推移而改变 假设某个应用程序 医疗 需要相当精确地跟踪一个人的性别
  • WPF 用户控件上下文菜单可见性绑定

    我的用户控件上下文菜单可见性无法绑定依赖属性 任何想法 这是我的 WPF 代码
  • 如何在C#中多次使用StopWatch?

    我有执行不同操作的简短代码 我想测量执行每个操作所需的时间 我在这里阅读了有关秒表类的信息 并且想要优化我的时间测量 我的函数调用了 5 个其他函数 我想在不声明的情况下测量每个函数 stopwatch sw1 new stopwatch
  • 将 C# 对象发送到 webapi 控制器

    我正在尝试将 C 对象传递给 Web api 控制器 该 API 配置为存储发布到它的 Product 类型的对象 我已经使用 Jquery Ajax 方法成功添加了对象 现在我尝试在 C 中获得相同的结果 我创建了一个简单的控制台应用程序
  • 在appendChild之后添加事件监听器

    我创建一个元素 eltTooltip with document createElement等等并将其添加到 DOM 像这样 idTooltip包含id of eltTooltip document body appendChild elt
  • 如何在 java SSL 客户端应用程序中支持多个 TrustStore

    在我们的 java 应用程序中 我们需要使用 https 协议与 SSL 上的服务器列表进行通信 要通信的服务器列表将在运行时更改 最初我们没有任何服务器的证书 在运行时 我们将获取新的服务器证书并将公钥证书添加到信任库中 并且与服务器的任
  • 在 swift 中按串行顺序同步多个 Web 服务调用

    我点击 Web 服务 URL 10 次并得到响应 我在用Alamofire and SwiftyJSON 这是我的控制器代码 class ViewController UIViewController let dispatchGroup D