PromiseKit从Swift2升级到Swift4后类型转换错误求助
问题分析与解决方案
我来帮你拆解下这个升级后遇到的问题——这本质是PromiseKit从适配Swift 2的旧版本升级到Swift 4对应的新版本(一般是v6.x及以上)时,API规则发生了重大变化导致的,核心是两个关键点:
1. Guarantee与Promise的类型边界变严格了
在Swift 2时代的PromiseKit中,代表「不会失败的异步操作」的Guarantee和代表「可能失败的异步操作」的Promise可以比较宽松地互相转换,但新版本里它们是独立的类型,无法隐式转换。
从你的代码看,MultiCache的get()方法大概率返回的是Guarantee(缓存读取操作通常不会抛出错误),那么when组合多个Guarantee后返回的是Guarantee<(T1, T2)>类型,但你的函数声明返回的是Promise<NSArray>,这就触发了类型不匹配的错误。
2. then与map的职责被明确拆分
旧版PromiseKit里,then既可以用来串联异步操作(返回新的Promise),也可以同步转换结果值;但新版本中:
then仅用于返回新的Promise/Guarantee的异步链式场景- 同步转换结果值需要用
map方法
你当前的闭包是直接返回NSArray(同步计算的结果),用then就不符合新版本的API规则,这也是错误的诱因之一。
修改后的代码示例
针对你的代码,只需要做两处关键调整:
- 把
then替换成map来处理同步值转换 - 如果函数必须返回
Promise,就用.promise方法把Guarantee转换成Promise(或者直接把函数返回类型改成Guarantee<NSArray>,更贴合缓存操作的语义)
func getPlayerGameLog(sportName: String) -> Promise<NSArray> { let team = (self as? PlayerWithPositionAndGame)?.team let position = (self as? PlayerWithPositionAndGame)?.position if sportName == "mlb" { return when(fulfilled: Data.mlbPlayerGameLogs[id].get(), Data.sportsTeams[sportName].get()) .map { (result, teams) -> NSArray in if result.count == 0 { return [] } else { // 你的业务处理代码 return gameStats } } .promise // 将Guarantee转换为Promise,匹配函数返回类型 } else if sportName == "nfl" { return when(fulfilled: Data.nflPlayerGameLogs[id].get(), Data.sportsTeams[sportName].get()) .map { (result, teams) -> NSArray in if result.count == 0 { return [] } else { // 你的业务处理代码 return gameStats } } .promise } else { return Data.nbaPlayerGameLogs[id].get() .map { gameLogs -> NSArray in return [] } .promise } }
额外建议
- 如果确认缓存操作不会失败,建议把函数返回类型改成
Guarantee<NSArray>,这样可以去掉.promise转换,类型语义更准确。 - 尽量把
NSArray/NSDictionary替换成Swift原生的[Any]/[String: Any](或者更具体的模型类型),Swift 4+对原生集合类型的支持更好,类型安全性也更高。
内容的提问来源于stack exchange,提问作者Konrad Wright
相关产品推荐
相关产品推荐

