为什么在 Playground 和单元测试中不调用 GCD 调度组通知

Why GCD dispatch group notify is not called in Playground and Unit tests

我的代码在 simulator/device 中运行,我正在尝试为其编写单元测试。但是,在单元测试中不会调用通知回调。这是 Playgrounds 的代码,它也没有调用通知回调。我怀疑我可能使用了错误的队列,但无法弄清楚我应该使用哪一个。

import UIKit

class Loader {

    func fetch(callback: ((_ result: String)-> Void)) {

        callback("SomeString")
    }
}

class MyService {

   var list: Array<String> = Array()
   var loader: Loader = Loader()
   var dispatchGroup = DispatchGroup()

    func loadList(callback: @escaping (()-> Void)) {

       for i in 1...3 {

           self.dispatchGroup.enter()

           self.loader.fetch(callback: { [weak self] (string) in

               self?.list.append(string)
               self?.dispatchGroup.leave()
           })
       }

       dispatchGroup.notify(queue: .main) {

           callback()
       }
   }
}

var service = MyService()
service.loadList {

    print("Done is not called")
}

更新

感谢@paulvs,我们需要启用无限期执行。但是,如何为单元测试启用它?

import UIKit
import PlaygroundSupport

class Loader {

    func fetch(callback: ((_ result: String)-> Void)) {

        callback("SomeString")
    }
}

class MyService {

    var list: Array<String> = Array()
    var loader: Loader = Loader()
    var dispatchGroup = DispatchGroup()

    func loadList(callback: @escaping (()-> Void)) {

        for i in 1...3 {

            self.dispatchGroup.enter()

            self.loader.fetch(callback: { [weak self] (string) in

                self?.list.append(string)
                self?.dispatchGroup.leave()
            })
        }

        dispatchGroup.notify(queue: .main) {

            callback()
        }
    }
}

PlaygroundPage.current.needsIndefiniteExecution = true

var service = MyService()
service.loadList {

    print("Done is called now!")
}

感谢@paulvs 和这个 post 的想法,这是单元测试所需的代码:

let service = MyService()

let expect = expectation(description: "longRunningFunction")

service.loadList {

    expect.fulfill()
}

self.waitForExpectations(timeout: 0.5) { error in

    XCTAssert(service.isLoaded, "Not loaded")
}