-2

我正在从 API 下载一些 JSON,但是在我们进入下一个屏幕之前必须完成另一个先决条件(动画)。

我决定使用它DispatchGroup来执行此操作,但也需要重新加载。

我想出了一个使用完成处理程序的解决方案,该处理程序要么移动到下一个屏幕,要么dispatchGroup.leave只是移动到下一个屏幕,因为我们只需要下载一次数据。

let dispatchGroup = DispatchGroup()
var userName: String?

func fetchData() {
    dispatchGroup.enter()
    dispatchGroup.enter()
    
    resolveDataRequirements(dispatchGroup.leave)
    
    dispatchGroup.notify(queue: .main) { [weak self] in
        self?.moveToNextScreen()
    }
}

func resolveDataRequirements(_ completion: @escaping(() -> Void)) {
    api.resolve { [weak self] result in
        switch result {
        case .success(let user):
            self?.userName = user
            completion()
        case .failure:
            break
        }
    }
}

func moveToNextScreen() {
    // move to next screen, but passes the user
}

// reload data, and once the data is downloaded move to next screen
func reloadData() {
    resolveDataRequirements(moveToNextScreen)
}


// the user might choose to fetch data
fetchData()
// now if the user wanted to reload
reloadData()

现在的问题是这是在视图模型中 - 所以用户字符串实际上是我希望根除的状态。

有什么方法可以将用户字符串传递给dispatchGroup.notify或类似的?

4

1 回答 1

0

您可以使用 inout 属性并更改 userName 范围,如下所示:

func fetchData() {
    var userName = ""
    dispatchGroup.enter()
    dispatchGroup.enter()
    
    resolveDataRequirements(dispatchGroup.leave, &userName)
    
    dispatchGroup.notify(queue: .main) { [weak self] in
        self?.moveToNextScreen(userName)
    }
}

func resolveDataRequirements(_ completion: @escaping(() -> Void), _ userName: inout String) {
    api.resolve { [weak self] result in
        switch result {
        case .success(let user):
            userName = user
            completion()
        case .failure:
            break
        }
    }
}

func moveToNextScreen(_ userName: String) {
    print(userName)
}

我只是不明白你为什么要两次调用 enter() 而只调用一次 leave()

于 2021-09-08T14:55:07.140 回答