I’m creating code that performs asynchronous processing using the Promises library (https://github.com/google/promises). In this context, when building the app in Xcode 15.4 and Xcode 16.2, the behavior differs between the two.
I’m using version 2.1.1 of the library. Also, I’ve tried using the latest version, 2.4.0, but the result was the same.
Has anyone encountered the same issue or know an effective solution?
Here's a simple code that reproduces this issue.
@IBAction func tapButton(_: UIButton) {
_ = getInfo()
}
func getInfo() -> Promise<Void> {
Promise(on: .global(qos: .background)) { fulfill, _ in
self.callApi()
.then { apiResult -> Promise<ApiResult> in
print("\(#function), first apiResult: \(apiResult)")
return self.callApi() // #1
}
.then { apiResult in
print("\(#function), second apiResult: \(apiResult)") // #2
fulfill(())
}
}
}
func callApi() -> Promise<ApiResult> {
Promise(on: .global(qos: .background)) { fulfill, _ in
print("\(#function), start")
self.wait(3)
.then { _ in
let apiResult = ApiResult(message: "success")
print("\(#function), end")
fulfill(apiResult)
}
}
}
struct ApiResult: Codable {
var message: String
enum CodingKeys: String, CodingKey {
case message
}
}
The Swift Language version in the build settings is 5.0.
The console output when running the above code is as follows:
- When built with Xcode 15.4:
2025/03/21 10:10:46.248 callApi(), start
2025/03/21 10:10:46.248 wait 3.0 sec
2025/03/21 10:10:49.515 callApi(), end
2025/03/21 10:10:49.535 getDeviceInfo(), first apiResult: ApiResult(message: "success")
2025/03/21 10:10:49.535 callApi(), start
2025/03/21 10:10:49.536 wait 3.0 sec
2025/03/21 10:10:52.831 callApi(), end
2025/03/21 10:10:52.832 getDeviceInfo(), second apiResult: ApiResult(message: "success")
The process proceeds from #1 to #2 after completing the code comment in #1.
- When built with Xcode 16.2:
2025/03/21 09:45:33.399 callApi(), start
2025/03/21 09:45:33.400 wait 3.0 sec
2025/03/21 09:45:36.648 callApi(), end
2025/03/21 09:45:36.666 getDeviceInfo(), first apiResult: ApiResult(message: "success")
2025/03/21 09:45:36.666 callApi(), start
2025/03/21 09:45:36.666 wait 3.0 sec
2025/03/21 09:45:36.677 getDeviceInfo(), second apiResult: Pending: ApiResult
2025/03/21 09:45:39.933 callApi(), end
The process does not wait for the code comment in #1 to finish and outputs the #2 print statement first.
Additionally, even with Xcode 16.2, when changing the #2 line to "print("(#function), second apiResult: (apiResult.message)")", the output becomes as follows. From this, it seems that referencing the ApiResult type, which is not a String, might have some effect on the behavior.
2025/03/21 10:05:42.129 callApi(), start
2025/03/21 10:05:42.131 wait 3.0 sec
2025/03/21 10:05:45.419 callApi(), end
2025/03/21 10:05:45.437 getDeviceInfo(), first apiResult: ApiResult(message: "success")
2025/03/21 10:05:45.437 callApi(), start
2025/03/21 10:05:45.437 wait 3.0 sec
2025/03/21 10:05:48.706 callApi(), end
2025/03/21 10:05:48.707 getDeviceInfo(), second apiResult: success
Thank you in advance