skip to Main Content

I was following the tutorial here:
https://youtu.be/SKkh2ZFTgdY?t=2382

At ~39:42 he finishes adding a button that is hidden until you select one of the visible buttons.

When I do that I get this error:

CompileDylibError: Failed to build DayView.swift

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

…/DayView.1.preview-thunk.swift:35:76: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
@_dynamicReplacement(for: body) private var __preview__body: some View {
^

Notice how the if selectedDate == date {... occurs twice in the code below.
If I change either one of those to if true {... then the error goes away.

Could someone explain why that would make the error go away? Am I not allowed to have two of the same if statements within this context? Is there a way around that?

I wonder if I’m not understanding something about how @State vars work and maybe I’m accidentally creating an infinite loop?

struct DayView: View {
    // dates that can be selected
    @State var dates = [
        Calendar.current.date(byAdding: .hour, value: 1, to: Date())!,
        Calendar.current.date(byAdding: .hour, value: 2, to: Date())!,
        Calendar.current.date(byAdding: .hour, value: 3, to: Date())!,
        Calendar.current.date(byAdding: .hour, value: 4, to: Date())!,
    ]
    
    // watching which date is selected
    @State var selectedDate: Date? // ? makes it optional, sometimes we don't have a selected date
    
    var body: some View {
        ScrollView {
            VStack {
                Text("Today's Date")
                Divider()
                    .padding(.vertical)
                Text("Select A Time")
                    .font(.largeTitle)
                    .bold()
                ForEach(dates, id:.self) { date in
                    HStack {
                        Button {
                            withAnimation {
                                selectedDate = date
                            }
                        } label: {
                            Text(date.timeFromDate())
                                .bold()
                                .padding()
                                .frame(maxWidth: .infinity)
                                .foregroundColor(selectedDate == date ? .white : .blue)
                                .background(
                                    ZStack {
                                        // change one of these to "if true" and the error goes away 1/2
                                        if selectedDate == date {
                                            // the button is selected
                                            RoundedRectangle(cornerRadius: 10)
                                                .fill(.blue.opacity(0.2))
                                        }
                                        else {
                                            // the button is not selected
                                            RoundedRectangle(cornerRadius: 10)
                                                .stroke()
                                        }
                                    }
                                )
                        }
                        // change one of these to "if true" and the error goes away 2/2
                        if selectedDate == date {
                            // the button is selected, insert a button so they can navigate to another page
                            NavigationLink {
                                EmptyView()
                            } label: {
                                Text("Next")
                                    .bold()
                                    .padding()
                                    .frame(maxWidth: .infinity)
                                    .background(
                                        RoundedRectangle(cornerRadius: 10)
                                            .foregroundColor(.blue)
                                    )
                            }
                        }
                    }
                }
            }
        }
        .navigationTitle("Day Of The Week")
        .navigationBarTitleDisplayMode(.inline)
    }
}

The second occurrence of if selectedDate == date {... is where that dark blue NavigationLink(basically a button) is added. That dark blue button only appears if you select one of the lighter buttons. That’s why it’s placed within the if condition.


Edit Dec 25

re Roy Rodney:
I made the MRE below. In doing so I noticed if I remove/modify any 1 of the 5 lines I commented the preview will compile successfully. So if I sacrifice .bold() for example it will compile.

Edit Dec 26
I tried to compile the working MRE this morning with .bold() commented out and it failed, it should have been successful. Then I just uncommented .bold(), waited for it to fail, and then commented out the .bold() again and it compiled successfully. I’m very confused.

re Joakim Danielson:
I used Product > Clean Build Folder. Then I restarted Xcode. I got the same error as before.

re son:
I tried to update to the same software versions as you but apparently my macbook is from 2015 and not compatible with macOSVentura which is required to install Xcode 14.3.

I’m using:
MacBook Pro (Retina, 15-inch, Mid 2015)
MacOS 12.7.2 (21G1974)
Xcode Version 14.2 (14C18)
Simulator says: iOS 16.2 (20C52)

import SwiftUI

struct DayView: View {
    // dates that can be selected
    @State var dates = [
        Calendar.current.date(byAdding: .hour, value: 1, to: Date())!
    ]
    
    // watching which date is selected
    @State var selectedDate: Date?
    
    var body: some View {
        VStack {
            ForEach(dates, id:.self) { date in
                HStack {
                    Button {
                        selectedDate = date
                    } label: {
                        Text(date.timeFromDate()) // set this to Text("test") to compile successfully 1/5
                            .bold() // remove this line to compile successfully 2/5
                            .padding()
                            .frame(maxWidth: .infinity)
                            .foregroundColor(selectedDate == date ? .white : .blue) // remove this line to compile successfully 3/5
                            .background(
                                ZStack {
                                    if selectedDate == date { // change this to "if true"  to compile successfully 4/5
                                        RoundedRectangle(cornerRadius: 10)
                                            .fill(.blue.opacity(0.2))
                                    }
                                    else {
                                        RoundedRectangle(cornerRadius: 10)
                                            .stroke()
                                    }
                                }
                            )
                    }
                    if selectedDate == date { // change this to "if true"  to compile successfully 5/5
                        NavigationLink {
                            EmptyView()
                        } label: {
                            Text("Next")
                                .padding()
                                .frame(maxWidth: .infinity)
                        }
                    }
                }
            }
        }
    }
}

extension Date {
    func timeFromDate() -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm a"
        return formatter.string(from: self)
    }
}

struct DayView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationStack {
            DayView()
        }
    }
}

3

Answers


  1. Chosen as BEST ANSWER

    Inspired by son's comment where he used a newer version of Xcode, I managed to aquire a macbook pro 2017 and installed:
    MacOS Ventura 13.6.3
    Xcode 15.1 (15C65)
    iOS 17.2

    Then I created a new Swift UI project and copied in the MRE(minimal reproducible example) into a swift file called DayView. It compiled successfully. So then I replaced the entire struct DayView definition using the original code I posted. That compiled successfully as well.

    To make sure, I went back to my macbook 2015. I created a new project and followed the same procedure as above. The code failed to compile.

    For that reason, I suspect my older macbook has something to do with it. I don't know exactly why or if it's possible to get this code working on my old macbook.


  2. When writing

    if selectedDate == date {
    

    you compare an optional to a non-optional Date, which are different types. Maybe this throws off the compiler. Try replacing with an unwrap:

    if let selectedDate, selectedDate == date {
    
    Login or Signup to reply.
  3. Well, let us look at the warning.

    1. "the compiler is unable to type-check this expression in reasonable time;"

    -> Let’s make the typing more explicit. Try adding an explicit type to your collection.

    @State var dates: [Date] = [
        Calendar.current.date(byAdding: .hour, value: 1, to: Date())!
    ]
    
    1. "try breaking up the expression into distinct sub-expressions"

    We can break up the view’s body, making it more readable for the compiler (sub-views are resolved independently) and humans alike!

    var body: some View {
            VStack {
                ForEach(dates, id:.self) { date in
                    HStack {
                        Button {
                            selectedDate = date
                        } label: {
                            buttonLabel(date: date)
                        }
                        if selectedDate == date {
                            navigationLink
                        }
                    }
                }
            }
        }
        
        private func buttonLabel(date: Date) -> some View {
            Text(date.timeFromDate()) // set this to Text("test") to compile successfully 1/5
                .bold() // remove this line to compile successfully 2/5
                .padding()
                .frame(maxWidth: .infinity)
                .foregroundColor(selectedDate == date ? .white : .blue) // remove this line to compile successfully 3/5
                .background(
                    ZStack {
                        if selectedDate == date { // change this to "if true"  to compile successfully 4/5
                            RoundedRectangle(cornerRadius: 10)
                                .fill(.blue.opacity(0.2))
                        }
                        else {
                            RoundedRectangle(cornerRadius: 10)
                                .stroke()
                        }
                    }
                )
        }
        
        private var navigationLink: some View {
            NavigationLink {
                EmptyView()
            } label: {
                Text("Next")
                    .padding()
                    .frame(maxWidth: .infinity)
            }
        }
    

    Hopefully, this will satisfy XCode! If not, more refactoring should do the trick.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search