Xcode 16编译报错:Predicate表达式过于复杂无法类型检查
Xcode 16编译Predicate宏时出现类型检查超时问题
在Xcode 16中编译代码时,遇到错误提示:"编译器无法在合理时间内对此表达式进行类型检查;尝试将表达式拆分为不同的子表达式",错误出现在#Predicate宏的展开位置。相同代码在Xcode 15中可正常编译运行,移除6个用||分隔的条件中的任意2个后,编译就能正常通过。
原代码
class FeaturesPredicate { class func predicate(_ enabledFeaturesName: String) -> Predicate<Caliber> { #Predicate { caliber in caliber.caliberData.featuresABCD.contains { feature in enabledFeaturesName == feature.name } || caliber.caliberData.featuresA.contains { feature in enabledFeaturesName == feature.name } || caliber.caliberData.featuresB.contains { feature in enabledFeaturesName == feature.name } || caliber.caliberData.featuresC.contains { feature in enabledFeaturesName == feature.name } || caliber.caliberData.featuresD.contains { feature in enabledFeaturesName == feature.name } || caliber.caliberData.featuresN.contains { feature in enabledFeaturesName == feature.name } } } }
宏展开后的代码
Foundation.Predicate({ caliber in PredicateExpressions.build_Disjunction( lhs: PredicateExpressions.build_Disjunction( lhs: PredicateExpressions.build_Disjunction( lhs: PredicateExpressions.build_Disjunction( lhs: PredicateExpressions.build_Disjunction( lhs: PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(caliber), keyPath: \.caliberData ), keyPath: \.featuresABCD ) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(feature), keyPath: \.name ) ) }, rhs: PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(caliber), keyPath: \.caliberData ), keyPath: \.featuresA ) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(feature), keyPath: \.name ) ) } ), rhs: PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(caliber), keyPath: \.caliberData ), keyPath: \.featuresB ) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(feature), keyPath: \.name ) ) } ), rhs: PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(caliber), keyPath: \.caliberData ), keyPath: \.featuresC ) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(feature), keyPath: \.name ) ) } ), rhs: PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(caliber), keyPath: \.caliberData ), keyPath: \.featuresD ) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(feature), keyPath: \.name ) ) } ), rhs: PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(caliber), keyPath: \.caliberData ), keyPath: \.featuresN ) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath( root: PredicateExpressions.build_Arg(feature), keyPath: \.name ) ) } ) })
解决方案
方案1:拆分表达式为独立子Predicate
将每个contains条件拆成单独的Predicate,再通过逻辑或组合,降低编译器类型检查的复杂度:
class FeaturesPredicate { class func predicate(_ enabledFeaturesName: String) -> Predicate<Caliber> { let featureABCD = #Predicate<Caliber> { $0.caliberData.featuresABCD.contains { $0.name == enabledFeaturesName } } let featureA = #Predicate<Caliber> { $0.caliberData.featuresA.contains { $0.name == enabledFeaturesName } } let featureB = #Predicate<Caliber> { $0.caliberData.featuresB.contains { $0.name == enabledFeaturesName } } let featureC = #Predicate<Caliber> { $0.caliberData.featuresC.contains { $0.name == enabledFeaturesName } } let featureD = #Predicate<Caliber> { $0.caliberData.featuresD.contains { $0.name == enabledFeaturesName } } let featureN = #Predicate<Caliber> { $0.caliberData.featuresN.contains { $0.name == enabledFeaturesName } } return featureABCD || featureA || featureB || featureC || featureD || featureN } }
方案2:重构数据结构合并特征数组
如果业务允许,将多个特征数组合并为一个统一数组,大幅简化Predicate逻辑:
// 先给CaliberData添加合并后的特征数组 extension CaliberData { var allFeatures: [Feature] { featuresABCD + featuresA + featuresB + featuresC + featuresD + featuresN } } // 简化后的Predicate实现 class FeaturesPredicate { class func predicate(_ enabledFeaturesName: String) -> Predicate<Caliber> { #Predicate { $0.caliberData.allFeatures.contains { $0.name == enabledFeaturesName } } } }
方案3:手动构建Predicate表达式
直接使用PredicateExpressionsAPI手动构建逻辑,避免宏展开时的深层嵌套:
class FeaturesPredicate { class func predicate(_ enabledFeaturesName: String) -> Predicate<Caliber> { let caliberArg = PredicateExpressions.build_Arg(Caliber.self) let caliberDataKeyPath = PredicateExpressions.build_KeyPath(root: caliberArg, keyPath: \.caliberData) // 逐个构建每个特征数组的检查表达式 let abcdCheck = PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath(root: caliberDataKeyPath, keyPath: \.featuresABCD) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath(root: PredicateExpressions.build_Arg(feature), keyPath: \.name) ) } let aCheck = PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath(root: caliberDataKeyPath, keyPath: \.featuresA) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath(root: PredicateExpressions.build_Arg(feature), keyPath: \.name) ) } let bCheck = PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath(root: caliberDataKeyPath, keyPath: \.featuresB) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath(root: PredicateExpressions.build_Arg(feature), keyPath: \.name) ) } let cCheck = PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath(root: caliberDataKeyPath, keyPath: \.featuresC) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath(root: PredicateExpressions.build_Arg(feature), keyPath: \.name) ) } let dCheck = PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath(root: caliberDataKeyPath, keyPath: \.featuresD) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath(root: PredicateExpressions.build_Arg(feature), keyPath: \.name) ) } let nCheck = PredicateExpressions.build_contains( PredicateExpressions.build_KeyPath(root: caliberDataKeyPath, keyPath: \.featuresN) ) { feature in PredicateExpressions.build_Equal( lhs: PredicateExpressions.build_Arg(enabledFeaturesName), rhs: PredicateExpressions.build_KeyPath(root: PredicateExpressions.build_Arg(feature), keyPath: \.name) ) } // 逐步组合逻辑或表达式 let combined = PredicateExpressions.build_Disjunction(lhs: abcdCheck, rhs: aCheck) let combined2 = PredicateExpressions.build_Disjunction(lhs: combined, rhs: bCheck) let combined3 = PredicateExpressions.build_Disjunction(lhs: combined2, rhs: cCheck) let combined4 = PredicateExpressions.build_Disjunction(lhs: combined3, rhs: dCheck) let final = PredicateExpressions.build_Disjunction(lhs: combined4, rhs: nCheck) return Predicate(final) } }
内容的提问来源于stack exchange,提问作者Deniss Fedotovs
相关产品推荐
相关产品推荐

