编译器无法键入检查这个表达式迅捷4?

在更新 xCode 之后,我的代码中出现了这个错误:

编译器无法以合理的方式对此表达式进行类型检查 试着把表达式分解成不同的子表达式

密码:

//check popup in window frame


let spaceFromLeftSide = cutOutViewX.constant + cutOutViewWidth.constant/2 - (options.textWidth + padding*2)/2


if spaceFromLeftSide < 0{


if options.side == .bottom {
messageRightSpaceFromBottomDot.constant -= spaceFromLeftSide - padding
}
else if options.side == .top{
messageRightSpaceFromTopDot.constant += spaceFromLeftSide - padding
}
}


let spaceFromRightSide = cutOutViewX.constant + cutOutViewWidth.constant/2 + (options.textWidth + padding*2)/2


if spaceFromRightSide > targetView.frame.size.width{


if options.side == .bottom {
messageRightSpaceFromBottomDot.constant -= spaceFromRightSide - ( targetView.frame.size.width )
}
else if options.side == .top{
messageRightSpaceFromTopDot.constant += spaceFromRightSide - ( targetView.frame.size.width )
}
}

线路错误:

let spaceFromRightSide = cutOutViewX.constant + cutOutViewWidth.constant/2 + (options.textWidth + padding*2)/2

怎么补救?

84488 次浏览

Just try to break up the expression to several simpler subexpression. E.g.:

let halfOfViewWidth = cutOutViewWidth.constant / 2
let textWidthAndPadding = options.textWidth + (padding * 2)
let spaceFromRightSide = cutOutViewX.constant + halfOfViewWidth + (textWidthAndPadding / 2)

EDIT

I noticed that I was able to fix this type of error also by providing explicit type conversions (e.g., instead of relying on the compiler to infer that by multiplying a CGFloat with an Int it should result in CGFloat, I have explicitly converted the Int to CGFloat). Seems that the problem lies indeed in types and automatic type inference and checking. While breaking up the the complex expression to smaller parts can be very useful to readability, you can solve the problem by being explicit about the types (the error message basically says that the compiler is unable do the type check - thus you can help it by providing explicit types where-ever possible).

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

This error appears when swift compiler finds the expression calculation lengthy. For more details check here

To resolve this, you just need to break your expression into smaller parts. Just like:

let cutOutxOrigin = 3 * cutOutViewX.constant / 2
let actualPadding = (options.textWidth + padding * 2) / 2


let spaceFromRightSide = cutOutxOrigin + actualPadding

So I have this kind of expression:

return (50 + textHeight) + (dateTextHeight + 16) + (5 + 8) + (16 + 20)

I knew I had to breakdown or make this expression shorter to get rid of the error. Like perhaps:

return (50 + textHeight) + (dateTextHeight + 16) + 49

Although true enough it helped the compiler to do its job, the main cause of the error is the optional Int textHeight. I think no matter how long your expression, it should be compile-able.

I have faced similar issue with different scenario

I was trying to create array of string

let selectedData = [
(data?.nose?.stuffyNose) ?? "",
(data?.nose?.sinusProblems) ?? "",
(data?.nose?.hayFever) ?? "",
(data?.nose?.sneezingAttacks) ?? "",
(data?.nose?.excessiveMucusFormation) ?? ""
]

I have already addd Brackets () but still was not working.


To fix this I have added type [String]

let selectedData:[String] = [
(data?.nose?.stuffyNose) ?? "",
(data?.nose?.sinusProblems) ?? "",
(data?.nose?.hayFever) ?? "",
(data?.nose?.sneezingAttacks) ?? "",
(data?.nose?.excessiveMucusFormation) ?? ""
]

Hope it is helpful to someone facing same issue

I had this error when I accidentally mixed in an optional in an expression. After force unwrapping the error went away.

let a : String = "A"
let b : String = "B"
let c = letterDictionary["C"]


let imageName : String = a + b + c //error
let imageName : String = a + b + c! //no error

This is indeed a memory problem. It happened to me, when I only 350 mb of free memory on my 16GB machine. Using f.e. CleanMyMac -> Free up memory resolved this problem.

I see this issue quite regularly when working with SwiftUI, and it's always been the result of a syntax error. I'm currently using Xcode 11.4.1, and it was true for earlier versions supporting SwiftUI.

For example, I just burned 50 mins with this error because I'd changed the name of a function parameter in another file. The compiler reported this error in a SwiftUI file that was completely untouched, except it invoked the function without the changed parameter name. Rather than explicitly pointing out the parameter name mismatch is baulked with this error.

This error occurs when compiler is confused. I ran into it doing a lengthy calculation that mixes various number types

I was able to remedy this by casting various sub-calculations into CGFloat. I did not need to "break up" expressions as suggested by some answers.

  • From: (some float expression) * someDouble / someInt
  • To: (some float expression) * CGFloat(someDouble / someInt)

By simply doing that :

    let array = [Int]()
let dic   = [Int : Double]()
    

let tuple = array.map { c -> (a: Int, b: Double) in return (a: c, b: dic[c]!) }.sorted(by: { (first, second) -> Bool in return first.b == second.b ? first.a < second.a : first.b > second.b }).first!

Xcode 11.6 takes 10 sec of Cpu with 4 processes running at 100% consuming a lot of Watts on my MacPro 2019 and i got the error : (The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions)

Even with only a map and a sort combined !

If i split in 2 :

let temporaryTupleArrayToAvoidTheCompilerBug = array.map { c -> (a: Int, b: Double) in return (a: c, b: dic[c]!) }


let tuple = temporaryTupleArrayToAvoidTheCompilerBug.sorted(by: { (first, second) -> Bool in return first.b == second.b ? first.a < second.a : first.b > second.b }).first!

It works.

The error message is here to hide a bug, the compiler can split the instruction and check the methods syntax separately.

One possible case is that i splice string with enum.

eg:

enum Fruit: String {
case apple
}


let fruit = Fruit.apple

then i splice occur the error

let url = "/api/" + fruit

fruit is a Enum field rather than a String. I fix with

let url = "/api/" + fruit.rawValue

This happened to me. I was passing two Float to a SwiftUI struct and subtracting one from the other inside, but by mistake I defined the Float inside the as Dates (damn you, copy-paste!).

It was basically this.

struct Something: View {
var minValue: Date
var maxValue: Date


var body: some View {
let valueDifference = maxValue - minValue
}
}

I was calling it like this:

let minValue: Float = 0
let maxValue: Float = 1


Something(minValue: minValue, maxValue: maxValue)

Note I'm actually passing two Float, but the struct is accepting them even though they're defined as Date.

As soon as I changed the Date types to Float the problem was gone.

I had an expression with several uses of an optional variable, with fallback values, like this:

if ((self.scrollView?.contentSize.width ?? 0.0) > 0.0) && ((self.scrollView?.contentSize.height ?? 0.0) > 0.0) && ((self.scrollView?.frame.size.height ?? 0.0) > 0.0) {

The error went away when I made a non-optional copy of the variable:

guard let scrollView = self.scrollView else { return }
if (scrollView.contentSize.width > 0.0) && (scrollView.contentSize.height > 0.0) && (scrollView.frame.size.height > 0.0) {

Depending on what you want to do when the optional variable is nil, this one-line version could also be useful:

if let scrollView = self.scrollView, (scrollView.contentSize.width > 0.0), (scrollView.contentSize.height > 0.0), (scrollView.frame.size.height > 0.0) {

I had the same problem here:

@State var sliderpos : CGFloat = (UIScreen.main.bounds.width-32)*(50/100)+(16-20) //causes error

But this works :

@State var sliderpos : CGFloat = (UIScreen.main.bounds.width-32)*(50/100)-4

I ran into this issue on Firebase when updating data for individual keys as per documentation.

// Update Cards
self.database.collection(FirebaseDatabaseKeys.cards).document(docId).setData([
"id": docId,
"cardNumber": card.cardNumber ?? "",
"isFavorite": card.isFavorite,
"numberOfCards": card.numberOfCards,
"playerName": card.playerName?.uppercased() ?? "",
"year": card.year ?? "",
"sport": card.sport ?? "",
"brand": card.brand ?? "",
"set": card.set ?? "",
"parallel": card.parallel ?? "",
"serial": card.serial ?? "",
"owner": uid ?? "",
CardSide.frontCard.imageKey: "",
CardSide.backCard.imageKey: ""
]) { err in
if let error = err {
print(error.localizedDescription)
}
}

I resolve it creating the dictionary prior to calling setData

    // Create Data
let cardData: [String: Any] = [
"id": docId,
"cardNumber": card.cardNumber ?? "",
"isFavorite": card.isFavorite,
"numberOfCards": card.numberOfCards,
"playerName": card.playerName?.uppercased() ?? "",
"year": card.year ?? "",
"sport": card.sport ?? "",
"brand": card.brand ?? "",
"set": card.set ?? "",
"parallel": card.parallel ?? "",
"serial": card.serial ?? "",
"owner": uid ?? "",
CardSide.frontCard.imageKey: "",
CardSide.backCard.imageKey: ""
]


// Update Cards
self.database.collection(FirebaseDatabaseKeys.cards).document(docId).setData(cardData) { err in
if let error = err {
print(error.localizedDescription)
}
}

I had two instances of this so far:

  • changed a view that needed a binding as an argument to one using an environmental object but still had a call to MyView($binding) instead of MyView(). In a completely different view, this error appeared. I commented out the most complex code (a switch statement with seven different views) and the compiler found the problem.

– tried something, didn't like it, got into a muddle, caused the error. Discarded all changes rather than trying to unpick the problem; error persisted even though it ran and built ok. Cleaned build folder, error went away.Sent computer to sleep, error came back. Cleaned build folder again, error went away (& project built). Compiler is clearly confused - if this persists, will send project to Apple. Further observation tells me that it builds and runs fine, the compiler is happy afterwards, thinks about it, and THEN throws the error, which has no effect on the project's ability to run.

I think I got him. I added several more views to the project (for now, without adding them to any view hierarchies, just sitting there quietly), and the error became permanent. So I looked at the file where the error is marked again, and decided I can do without the group. Since then, I haven't seen the error again.