SWIFTUI:用数组 属性 创建 Class - 符合 'ObservableObject'。 Class!不是结构
SWIFTUI: Create Class with Array property - witch conform to 'ObservableObject'. Class! NOT struct
我需要创建数组 属性 of class 符合 ObservableObject 协议。因为我要将它与过滤器、排序等一起使用-将 table 中的 select 记录显示在列表视图中
class SQS_Record: NSObject, ObservableObject {
@Published final var __idx: Int = -1
}
class Project: SQS_Record {
@objc dynamic var name: String = "" { willSet { objectWillChange.send() } }
}
class SQS_Table<RecordType: SQS_Record>: ObservableObject {
@Published var records = [RecordType]()
var rcount: Int {
return records.count
}
subscript (index: Int) -> RecordType {
get {
return records[index]
}
set(item) {
records[index] = item
}
}
Let projectsTbl = SQS_Table<Project>(...)
struct ProjectsListView: View {
// This is ERROR line - below
@StateObject private var itemsList = projectsTbl.records.sorted { [=15=].__idx < .__idx }
var body: some View {
NavigationView {
List() {
// Список
ForEach (itemsList, id: \.__id) { (proj: Project) in
ProjectElement(project: proj)
}
.onMove(perform: moveItem )
.onDelete(perform: delItem )
}
…
}
错误:通用结构 'StateObject' 要求“[Project]”符合 'ObservableObject'
如果我没看错你的问题,你的array
项是类。您可以将数组声明为 @State
,但只有对数组本身的更改(添加、排序、删除)才会导致重新计算 body
。
让我们试试:
struct ArrayOfObservableObjects: View {
@State private var store = (1 ... 5).map(Record.init)
var body: some View {
NavigationView {
List(store) { record in
Text(record.score.description)
}
.toolbar {
HStack {
Button("Shuffle") {
store.shuffle()
}
Button("Change First") {
store.first?.score = 666
}
Button("Add") {
store.insert(Record(store.count + 1), at: 0)
}
}
}
}
}
}
如你所见,“Change First”按钮实际上改变了一条“Record”的“score”,但是这个修改并没有显示出来。
如果要“发布”数组中每个元素的更改,则必须分几步进行:
- 让您的
Record
可见:
class Record: ObservableObject, Identifiable {
let id = UUID()
@Published var score: Int
init(_ score: Int) {
self.score = score
}
}
- 将您的数组包装在一个 ObservableObject 中:
class RecordStore: ObservableObject {
@Published var records: [Record] = (1 ... 5).map(Record.init)
- 订阅数组每个元素的变化
private var c: AnyCancellable?
init() {
subscribeToChanges()
}
func subscribeToChanges() {
c = records
.publisher
.flatMap { record in record.objectWillChange }
.sink { [weak self] in
self?.objectWillChange.send()
}
}
}
有效。但是缺少了一些东西(如果我们添加一个新元素,它将不会被观察到)。所以要完成:
class RecordStore: ObservableObject {
@Published var records: [Record] = (1 ... 5).map(Record.init) {
didSet {
subscribeToChanges() ///<<< HERE
}
}
private var c: AnyCancellable?
init() {
subscribeToChanges()
}
func subscribeToChanges() {
c = records
.publisher
.flatMap { record in record.objectWillChange }
.sink { [weak self] in
self?.objectWillChange.send()
}
}
}
和视图:
import Combine
import SwiftUI
struct ArrayOfObservableObjects: View {
@StateObject var store = RecordStore()
var body: some View {
NavigationView {
List(store.records) { record in
Text(record.score.description)
}
.toolbar {
HStack {
Button("Shuffle") {
store.records.shuffle()
}
Button("Change First") {
store.records.first?.score = 666
}
Button("Add") {
store.records.insert(Record(store.records.count + 1), at: 0)
}
}
}
}
}
}
我需要创建数组 属性 of class 符合 ObservableObject 协议。因为我要将它与过滤器、排序等一起使用-将 table 中的 select 记录显示在列表视图中
class SQS_Record: NSObject, ObservableObject {
@Published final var __idx: Int = -1
}
class Project: SQS_Record {
@objc dynamic var name: String = "" { willSet { objectWillChange.send() } }
}
class SQS_Table<RecordType: SQS_Record>: ObservableObject {
@Published var records = [RecordType]()
var rcount: Int {
return records.count
}
subscript (index: Int) -> RecordType {
get {
return records[index]
}
set(item) {
records[index] = item
}
}
Let projectsTbl = SQS_Table<Project>(...)
struct ProjectsListView: View {
// This is ERROR line - below
@StateObject private var itemsList = projectsTbl.records.sorted { [=15=].__idx < .__idx }
var body: some View {
NavigationView {
List() {
// Список
ForEach (itemsList, id: \.__id) { (proj: Project) in
ProjectElement(project: proj)
}
.onMove(perform: moveItem )
.onDelete(perform: delItem )
}
…
}
错误:通用结构 'StateObject' 要求“[Project]”符合 'ObservableObject'
如果我没看错你的问题,你的array
项是类。您可以将数组声明为 @State
,但只有对数组本身的更改(添加、排序、删除)才会导致重新计算 body
。
让我们试试:
struct ArrayOfObservableObjects: View {
@State private var store = (1 ... 5).map(Record.init)
var body: some View {
NavigationView {
List(store) { record in
Text(record.score.description)
}
.toolbar {
HStack {
Button("Shuffle") {
store.shuffle()
}
Button("Change First") {
store.first?.score = 666
}
Button("Add") {
store.insert(Record(store.count + 1), at: 0)
}
}
}
}
}
}
如你所见,“Change First”按钮实际上改变了一条“Record”的“score”,但是这个修改并没有显示出来。
如果要“发布”数组中每个元素的更改,则必须分几步进行:
- 让您的
Record
可见:
class Record: ObservableObject, Identifiable {
let id = UUID()
@Published var score: Int
init(_ score: Int) {
self.score = score
}
}
- 将您的数组包装在一个 ObservableObject 中:
class RecordStore: ObservableObject {
@Published var records: [Record] = (1 ... 5).map(Record.init)
- 订阅数组每个元素的变化
private var c: AnyCancellable?
init() {
subscribeToChanges()
}
func subscribeToChanges() {
c = records
.publisher
.flatMap { record in record.objectWillChange }
.sink { [weak self] in
self?.objectWillChange.send()
}
}
}
有效。但是缺少了一些东西(如果我们添加一个新元素,它将不会被观察到)。所以要完成:
class RecordStore: ObservableObject {
@Published var records: [Record] = (1 ... 5).map(Record.init) {
didSet {
subscribeToChanges() ///<<< HERE
}
}
private var c: AnyCancellable?
init() {
subscribeToChanges()
}
func subscribeToChanges() {
c = records
.publisher
.flatMap { record in record.objectWillChange }
.sink { [weak self] in
self?.objectWillChange.send()
}
}
}
和视图:
import Combine
import SwiftUI
struct ArrayOfObservableObjects: View {
@StateObject var store = RecordStore()
var body: some View {
NavigationView {
List(store.records) { record in
Text(record.score.description)
}
.toolbar {
HStack {
Button("Shuffle") {
store.records.shuffle()
}
Button("Change First") {
store.records.first?.score = 666
}
Button("Add") {
store.records.insert(Record(store.records.count + 1), at: 0)
}
}
}
}
}
}