Search code examples
jsonswiftswiftdata

Cannot convert value of type 'Int?' to expected argument type 'Binding<Int>' error in Swift


Getting a cannot convert value of type 'Int?' to expected argument type 'Binding'.

Trying to store a value in Book for SwiftData value for rating. Rating is not a value in JSON database while all other values are in the external JSON database and read from that database

//  Book.swift

import Foundation
import SwiftData

struct Result: Decodable {
    let bookObjects: [Book]
}

@Model
class Book: Decodable, Identifiable, Hashable {
    let id: String
    let title: String
    let authors: [String]
    let imageURL: URL
    let subjects: [String]
    let date_published: String
    let synopsis : String
    var rating: Int?
    
    init(id: String, title: String, subjects: [String], authors: [String], date_published: String, synopsis: String, imageURL: URL, rating: Int) {
        self.id = id
        self.title = title
        self.subjects = subjects
        self.authors = authors
        self.date_published = date_published
        self.synopsis = synopsis
        self.imageURL = imageURL
        self.rating = rating
    }
    
//  SavedFavBookCard.swift

import SwiftUI
import SwiftData

struct SavedFavBookCard: View {
    @State private var searchText = ""
    @Environment(\.modelContext) private var context
    var bookSavedObject: Book
                                    
    var body: some View {
            LabeledContent {
                LoadingImage(url: bookSavedObject.imageURL)
                .frame(width: 50)
                .padding(30)
            } //end LabeledContent
        label: {
            Text(bookSavedObject.title)
                .foregroundColor(.white)
                .scaledFont(name: "Kanit-Medium", size: 15)
            if bookSavedObject.authors.isEmpty {  //array is empty
                Text("No author")
                    .scaledFont(name: "Kanit-Medium", size: 14)
            }
            else {
                Text(bookSavedObject.authors[0])
                    .scaledFont(name: "Kanit-Medium", size: 14)
            }
            RatingView(rating: bookSavedObject.rating)

//  RatingView.swift
import SwiftUI

struct RatingView: View {
    @Binding var rating: Int

    var label = ""
    var maximumRating = 5

    var offImage: Image?
    var onImage = Image(systemName: "star.fill")

    var offColor = Color.gray
    var onColor = Color.yellow

    var body: some View {
        HStack {
            if label.isEmpty == false {
                Text(label)
            }

            ForEach(1..<maximumRating + 1, id: \.self) { number in
                Button {
                    rating = number
                } label: {
                    image(for: number)
                        .foregroundStyle(number > rating ? offColor : onColor)
                }
            }
        }
        .buttonStyle(.plain)
    }

    func image(for number: Int) -> Image {
        if number > rating {
            offImage ?? onImage
        } else {
            onImage
        }
    }
}

Solution

  • First make the model property bindable

    @Bindable var bookSavedObject: Book
    

    And then change your model so that rating is not optional

    var rating: Int = 0
    

    And lastly change the call to the rating view

    RatingView(rating: $bookSavedObject.rating)