如何使用嵌套结构管理 SwiftUI 状态?

Mak*_*aus 7 swift swiftui

我有以下从 protobufs 生成的结构,所以它们不能直接修改:

// This file can not be modified
// It's auto-generated from protobufs

struct Shelf {
  var id: Int
  var title: String

  var books: [Books]
}

struct Book {
  var id: Int
  var title: String

  var pages: [Pages]
  var shelfId: Int
}

struct Page {
  var id: Int
  var content: String

  var bookId: Int
}
Run Code Online (Sandbox Code Playgroud)

在使用 Books+Pages 创建或修改新书架时,在 3 个嵌套的 SwiftUI 视图之间传递状态的正确方法是什么?我希望允许用户通过嵌套视图一次创建整个书架,并在他位于顶部视图并单击“保存”时将书架 + 书籍 + 页面保存到后端一次。

意见

我试图为对象创建一个扩展以符合“ObservableObject”,但失败了: Non-class type 'Shelf' cannot conform to class protocol 'ObservableObject'

Geo*_*e_E 13

我做了完整的项目,来演示如何传递数据。

如果您想下载完整的项目以查看所有代码,它可以在 GitHub 上的GeorgeElsham/BookshelvesExample上找到。这是项目的样子:

项目动图

这个项目与我对SwiftUI 的回答非常相似——将数据传递到不同的视图

作为总结,我创建了一个ObservableObject@EnvironmentObject. 它看起来像这样:

class BookshelvesModel: ObservableObject {

    @Published var shelves = [...]
    var books: [Book] {
       shelves[shelfId].books
    }
    var pages: [Page] {
       shelves[shelfId].books[bookId].pages
    }
    
    var shelfId = 0
    var bookId = 0
    
    func addShelf(title: String) {
        /* ... */
    }
    func addBook(title: String) {
        /* ... */
    }
    func addPage(content: String) {
        /* ... */
    }
    
    func totalBooks(for shelf: Shelf) -> String {
        /* ... */
    }
    func totalPages(for book: Book) -> String {
        /* ... */
    }
}
Run Code Online (Sandbox Code Playgroud)

然后所有视图都使用NavigationLink. 希望这对你有用!


如果您要手动重新制作,请确保更换

let contentView = ContentView()
Run Code Online (Sandbox Code Playgroud)

let contentView = ContentView().environmentObject(BookshelvesModel())
Run Code Online (Sandbox Code Playgroud)

SceneDelegate.swift.