AAV
AAV

Reputation: 423

SwiftUI Bind to core data object inside foreach

I am not able to bind the bookName from my Core Data object to a TextField inside a ForEach loop. How can I get this binding to work? I want the bookName value to be saved to Core Data when it changes.

I am receiving an error that says: Cannot find $book in scope.

extension Book: Identifiable {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Book> {
        return NSFetchRequest<Book>(entityName: "Book")
    }
    
    @NSManaged public var id: UUID?
    @NSManaged public var bookName: String?
    
    var wrappedBookName: String {
        bookName ?? ""
    }
}

struct BookListView: View {
    @FetchRequest(entity: Book.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Book.rankNumber, ascending: false)]) var books: FetchedResults<Book>
    
    var body: some View {
        ForEach(books) { book in
            TextField("Book Name", text: $book.bookName)  //Error: cannot find $book in scope
        }
    }
}

Upvotes: 3

Views: 1854

Answers (1)

davidev
davidev

Reputation: 8517

I love CoreData with SwiftUI. It works just so simple. Just create a new edit view with ObservedObject of Book.

struct EditView : View {
    @ObservedObject var book: Book
    
    init(book: Book) {
        self.book = book
    }
    
    var body : some View {
        TextField("Name", text: $book.bookName)
    }
}

And that's it. Then you can send $book.bookName as Binding to the String.

However, make sure! you have declared bookName as non-optional value in CoreData. TextField requires a Binding<String>, NOT a Binding<String?>

Use that EditView inside your ForEach and you are ready to go:

ForEach(books) { book in
    EditView(book: book)

Upvotes: 6

Related Questions