SwiftUI Table does not work when trying to use Int values

Hello Everyone, I am trying to get a SwiftUI Table to display content from my data model. It works as expected if I only use String values in the table, but if I try and use an Int value my app will no longer compile. It just sits there and I have to stop it manually. The only error I receive says "CompileSwiftSources Failed with a nonzero exit code" My code of the data model:

import Foundation

struct AlbumTracks: Identifiable {

    var artistName: String

    var artworkURL: String

    var composerName: String

    var discNumber: Int

    var durationInMillis: Int

    var isrc: String

    var name: String

    var id: String

    var releaseDate: String

    var trackNumber: Int

    

    init(artistName: String, artworkURL: String, composerName: String, discNumber: Int!, durationInMillis: Int!, isrc: String, name: String, id: String, releaseDate: String, trackNumber: Int!) {

        self.artistName = artistName

        self.artworkURL = artworkURL

        self.composerName = composerName

        self.discNumber = discNumber

        self.durationInMillis = durationInMillis

        self.isrc = isrc

        self.name = name

        self.id = id

        self.releaseDate = releaseDate

        self.trackNumber = trackNumber

    }

}

Here is the code for my view:

struct AlbumDetailView: View {

    @Environment(\.presentationMode) var presentationMode

    @Binding var albumId: String

    @State var searchResults = [AlbumDetails]()

    @State var albumTracks = [AlbumTracks]()

   

    var body: some View {

        

        VStack (alignment: .leading) {

            Button(action: {

                presentationMode.wrappedValue.dismiss()

            }, label: {

                Image(systemName: "arrow.left")

            }).padding(.top).foregroundColor(.red)



        

        ForEach(searchResults, id:\.id) { albumDetail in

            HStack {

                WebImage(url: URL(string: albumDetail.artworkURL.replacingOccurrences(of: "{w}", with: "5000").replacingOccurrences(of: "{h}", with: "5000")))

                    .resizable()

                    .padding(.top, 10.0)

                    .frame(width: 400, height: 400)

                    .cornerRadius(5)

                    .shadow(radius: 2)

                

                VStack (alignment: .leading) {

                    Text("song id: \(albumDetail.id)")

                        .foregroundColor(.secondary)

                        .padding(2)

                    Text("title: \(albumDetail.name)")

                        .foregroundColor(.secondary)

                        .padding(2)

                    Text("artist: \(albumDetail.artistName)")

                        .foregroundColor(.secondary)

                        .padding(2)

                    Text("composer: \(albumDetail.copyright)")

                        .foregroundColor(.secondary)

                        .padding(2)

                    

                    Text("track number: \(albumDetail.trackCount)")

                        .foregroundColor(.secondary)

                        .padding(2)

                    

                    Text("release date: \(albumDetail.releaseDate)")

                        .foregroundColor(.secondary)

                        .padding(2)

                    Text("isrc: \(albumDetail.upc)")

                        .foregroundColor(.secondary)

                        .padding(2)

                }

                .font(.system(size: 14))

                

            }

            

            Text("\(albumDetail.editorialNotesStandard)")

                .font(.system(size: 14))

                .foregroundColor(.secondary)

                .padding(2)

            

           

            Table(albumTracks) {

                TableColumn("disc", Int: \.discNumber)

                TableColumn("track", value: \.releaseDate)

                TableColumn("title", value: \.name)

                TableColumn("artist", value: \.artistName)

                TableColumn("duration ms", value: \.releaseDate)

                TableColumn("release date", value: \.releaseDate)

                TableColumn("isrc", value: \.isrc)

                TableColumn("track id", value: \.id)

                

                }

            

               

        }

            

        }

        .padding(.leading, 20.0)

        .frame(minWidth:800, idealWidth: 1000, maxWidth: .infinity, minHeight:600, idealHeight: 800, maxHeight: .infinity)

        .onAppear {

            SKCloudServiceController.requestAuthorization { (status) in

                if status == .authorized {

                    self.searchResults = AppleMusicAPI().getAlbumDetails(self.albumId)

                    self.albumTracks = AppleMusicAPI().getAlbumTracks(self.albumId)

                    

                }

            }

        }

    }

}

Any Help is much appreciated! Thanks!

Answered by OOPer in 693065022

I tried your code with Xcode 3.1 and got the following error:

(I needed to fill many parts missing in your shown code, so some other parts still hidden may be affecting.)

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

The error is far from kind enough for fixing the issue, but it may very often caused by some obvious syntax errors in a ViewBuilder.

As far as I check the code, this line is obviously odd:

                    TableColumn("disc", Int: \.discNumber)

TableColumn does not have an initializer init(_:Int:).

And any initializers of TableColumn taking a KeyPath to Int requires RowValue as NSObject.


So, a simple workaround may be defining an extension which return String.

extension AlbumTracks {
    var discNumberString: String {
        String(discNumber)
    }
}

And use it as follows:

                    TableColumn("disc", value: \.discNumberString)

But as already noted, other parts may be affecting. If this workaround does not work, you may need to show more info.

Can you show enough code to compile your code? Especially, what is AlbumDetails? In addition, AppleMusicAPI and WebImage are also needed.

Accepted Answer

I tried your code with Xcode 3.1 and got the following error:

(I needed to fill many parts missing in your shown code, so some other parts still hidden may be affecting.)

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

The error is far from kind enough for fixing the issue, but it may very often caused by some obvious syntax errors in a ViewBuilder.

As far as I check the code, this line is obviously odd:

                    TableColumn("disc", Int: \.discNumber)

TableColumn does not have an initializer init(_:Int:).

And any initializers of TableColumn taking a KeyPath to Int requires RowValue as NSObject.


So, a simple workaround may be defining an extension which return String.

extension AlbumTracks {
    var discNumberString: String {
        String(discNumber)
    }
}

And use it as follows:

                    TableColumn("disc", value: \.discNumberString)

But as already noted, other parts may be affecting. If this workaround does not work, you may need to show more info.

It worked! Even with me posting the wrong code, it worked!

As far as I check the code, this line is obviously odd:

                TableColumn("disc", Int: \.discNumber)

Yes, this is obviously odd and was just something I tried before posting on here. Normally that is not there and the disc number is set up like the rest of them. But your extension worked perfectly! Thanks so much for that!

Just curious but what do you mean by

(I needed to fill many parts missing in your shown code, so some other parts still hidden may be affecting.)

I did not hide any parts of my code. I just forgot to format it after pasting my code here. Is there another reason you say parts were missing? Like am I missing some code that should usually be there but isn't? Except for the issues with Tables, everything works perfectly and now works with Tables thanks to your input.
I really appreciate the response! Thanks again!

I have a follow up question that I bet you know the answer to. Of course no worries if you don't have the time. How would I get [genreNames] into the table? The genreNames that come back are formatted as an Array of Strings. In my data model I had entered the genreNames as [String] as shown here:

struct SongDetails {

    var albumName: String

    var artistName: String

    var artworkURL: String

    var composerName: String

    var discNumber: Int

    var durationInMillis: Int

    var genreNames: [String]

    var isrc: String

    var name: String

    var id: String

    var releaseDate: String

    var trackNumber: Int

but when parsing the JSON when it returns from the API call, it would not let me label the genreNames with .string!

URLSession.shared.dataTask(with: musicRequest) { (data, response, error) in

            guard error == nil else { return }

            if let json = try? JSON(data: data!) {

                let result = (json["data"]).array!

                for songDetail in result {

                    let attributes = songDetail["attributes"]

                    let song = SongDetails(albumName: attributes["albumName"].string!,

                               artistName: attributes["artistName"].string!,

                               artworkURL: attributes["artwork"]["url"].string!,

                               composerName: attributes["composerName"].string ?? "-",

                               discNumber: attributes["discNumber"].int!,

                               durationInMillis: attributes["durationInMillis"].int!,

                               genreNames: attributes["genreNames"].arrayValue,

                               isrc: attributes["isrc"].string!,

                               name: attributes["name"].string!,

                               id: attributes["playParams"]["id"].string!,

                               releaseDate: attributes["releaseDate"].string!,

                               trackNumber: attributes["trackNumber"].int!)

                    songDetails.append(song)

                    print(songDetails)

                }

so I eventually figured out that it had to be an arrayValue or an Array. So now I have that working but I can't seem to convert the array into a string using join() . I just want a string of the genreNames to put into once table cell.
I also re-wrote everything to use Codable, but got stuck at the east same point. So basically I want to get [genreNames] returned from the JSON to a string such as: Alternative, Indie, Pop. I hope the is enough info for you or else anyone trying to help. This is the last piece I am struggling with.

Thanks!

SwiftUI Table does not work when trying to use Int values
 
 
Q