简体   繁体   中英

Maddening error in SwiftUI that doesn't seem to make sense. Is there a bug in the compiler?

I'm trying to build a version of the Splendor Board game in SwiftUI purely for learning purposes. I'm building the token stack views and am getting a really confusing error. Every time I do a change, the canvas is taking forever and then coming up with this error:

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

From what I can see my code is error free and in reasonable style (though please feel free to give feedback if it could be improved). The error seems to be contingent on the offset() function on line 11 - if I comment it out, the error goes away, but in any case, the code needs that offset to work. I can't see why this should be the case.

The error itself suggests breaking the code into smaller chunks - but it's already pretty small!

By way of explanation, the TokenView is meant to build a token with an image of a gem - think of a poker chip. The TokenStackView is meant to build a stack of token views, each slightly more offset than the previous, with the last chip sitting slightly more askew. The 'showImage' boolean was my attempt to make compiling easier for the compiler - but this didn't fix the error.

My code did have a few more modifiers to make it look good, fit in frames, etc, but I have since taken them all out in an attempt to fix this error.

Any assistance to resolve this would be greatly appreciated!

import SwiftUI

struct TokenStackView: View {
    var gemType: GemType
    var gemsCount: Int
    
    var body: some View {
        ZStack{
            ForEach (0..<gemsCount-1) { index in
                TokenView(gemType: self.gemType, showImage: false)
    //This line here causes the error:

                  .offset(x: CGFloat(index * offsetFactor), y: CGFloat(-index * offsetFactor))
            }
            TokenView(gemType: self.gemType, showImage: true)
        }
    }
    
    //Control Panel
    let offsetFactor: CGFloat = 10
}

struct TokenStackView_Previews: PreviewProvider {
    static var previews: some View {
        TokenStackView(gemType: .ruby, gemsCount: 5)
    }
}

Here is TokenStackView.swift:

import SwiftUI

struct TokenView: View {
    var gemType: GemType
    var showImage: Bool
    
    var body: some View {
        ZStack{
            Circle()
                .stroke(self.gemType.secondaryColour(), lineWidth: lineWidth)
                .offset(x: -offset, y: offset)
            if showImage {
                Image(self.gemType.rawValue + "-token")
                    .clipShape(Circle())
            }
            Circle()
                .stroke(self.gemType.primaryColour() ,lineWidth: lineWidth)
        }
        .frame(width: frameWidthHeight, height: frameWidthHeight, alignment: .center)
    }
    
    let frameWidthHeight: CGFloat = 550
    let lineWidth: CGFloat = 20
    let offset: CGFloat = 10
}

struct TokenView_Previews: PreviewProvider {
    static var previews: some View {
        TokenView(gemType: .diamond, showImage: true)
    }
}

Edit: fixed a minor error in code - the compiler error persists.

This erros mostly happens when you are doing something wrong but complier can't say what it is. sometimes it happens when there is just a long long expression and complier is unhappy with it and you'll just need to break it down to a few expressions and the error will go away.

in this case, i saw one problem with your code that is most likely causing this problem. i'm not sure if there are more too (probably not), but here's the one i found:

.offset(x: index * offsetFactor, y: -index * offsetFactor)

index and offsetFactor are of type Int . you should simply wrap them in a CGFloat to convert them to CGFloat , because .offset(x:y:) method accepts CGFloats, not Ints:

.offset(x: CGFloat(index * offsetFactor), y: CGFloat(-index * offsetFactor))

The following variant compiled well. Tested with Xcode 12

TokenView(gemType: self.gemType, showImage: false)
  .offset(x: CGFloat(index) * self.offsetFactor, y: CGFloat(-index) * self.offsetFactor)

Update: by changing to use self in self.offsetFactor makes it compilable with Xcode 11.2 as well

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM