I know this has been asked before, but I just can't figure out why it isn't working for me. I'm pretty new to coding, so any help would be appreciated.
Trying to have BookSheetView open as a sheet after selecting a cell in my lazyvgrid.
struct LibraryView: View {
@State private var showingSheet = false
let book: Book
let spacing: CGFloat = 10
var gridItems: [GridItem] {
[GridItem(.adaptive(minimum: 180, maximum: 180))]
}
var body: some View {
Text("Text to come")
.multilineTextAlignment(.leading)
.navigationTitle("Library")
ScrollView {
LazyVGrid(columns: gridItems,
spacing: spacing
)
{ ForEach(books, id: \.self) { book in
Button {
showingSheet = true
} label: {
BookTileModel(book: book)
}
// NavigationLink(destination: BookSheetView(book:book),
// label: {BookTileModel(book: book)})
}
}
}
// Start of sheet
.sheet(isPresented: $showingSheet) {
BookSheetView(book: book)
}
// End of sheet
}
}
struct LibraryView_Previews: PreviewProvider {
static var previews: some View {
LibraryView(book: books[1])
}
}
If I use a button, I can get the sheet to open to the right view, but it's not passing the information to the sheet, and if I use a NavigationLink, I get the right information, but as a full page, not a sheet.
I've looked at a bunch of similar posts and watched some tutorials, but I just can't quite figure it out :(
UPDATED CODE
import Foundation
import SwiftUI
extension String: Identifiable {
public var id: String { self }
}
struct GridView: View {
@State private var selected: String? = nil
let book: Book
var gridItems: [GridItem] {
[GridItem(.adaptive(minimum: 180, maximum: 180))]
}
var body: some View {
ScrollView (showsIndicators: false) {
LazyVGrid(columns: gridItems) {
ForEach(book, id: \.self) { item in //ERROR Generic struct 'ForEach' requires that 'Book' conform to 'RandomAccessCollection'
Button(action: {
selected = item
}) {
BookTileModel(book: book)
}
}
}
}.sheet(item: $selected) { item in
BookSheetView(book: item) // ERROR Cannot convert the value of type 'String' to expected argument type 'Book'
}
}
}
Here is a working example, notice the comments:
struct ContentView: View {
let books: [Book] = [
Book(title: "Anna Karenina", author: "Tolstoi"),
Book(title: "To Kill a Mockingbird", author: "Harper Lee"),
Book(title: "The Great Gatsby", author: "F. Scott Fitzgerald"),
Book(title: "One Hundred Years of Solitude", author: "Gabriel García Márquez "),
Book(title: "Mrs. Dalloway", author: "Virginia Woolf’"),
Book(title: "Jane Eyre", author: "Charlotte Brontë’"),
]
@State private var selected: Book? = nil // selection has to be an optional of the Type you use in the ForEach, here Book?
var gridItems: [GridItem] {
[GridItem(.adaptive(minimum: 180, maximum: 180))]
}
var body: some View {
ScrollView (showsIndicators: false) {
LazyVGrid(columns: gridItems) {
ForEach(books) { item in // you cant ForEach over one book, it has to be an array of books = [Book]
Button(action: {
selected = item
}) {
BookTileModel(book: item)
}
}
}
}.sheet(item: $selected) { item in
BookSheetView(book: item) // now that selected is of Type Book, this should work
}
}
}