如何将视图条目计数传输到 Class 方法
How to Transmit a View Entry Count to a Class Method
我在使用视图中的条目数计数时遇到问题。我特别需要知道什么时候视图中没有条目。我在下面的视图中放置了调试代码,并且视图计数 currants.curItem.count
正在按预期更新。 checkForUpdates() 中的计数状态不符合上述视图。
如果我没记错的话,我应该只在视图中使用@EnvironmentObject 或@ObservedObject。我真的需要某种可以传递给方法 checkForUpdates 的全局变量。当 checkForUpdates() 中的计数为非零时,它会崩溃,而在视图中它实际上为零。它还在 checkForUpdates() 中崩溃,并出现错误 Fatal error: No ObservableObject of type Currencies found。作为此视图的祖先,货币的 View.environmentObject(_:) 可能缺失。
struct manCurView: View {
@EnvironmentObject var currants: Currants
var body: some View {
List {
ForEach(currants.curItem, id: \.id) { item in
HStack {
Text(item.curCode)
.frame(width: 100, alignment: .center)
Text(item.cunName)
}
.font(.subheadline)
}
.onDelete(perform: removeItems)
}
.navigationBarTitle(Text("Manage Working Blocks"), displayMode: .inline)
HStack {
NavigationLink(destination: addCurView()) {Text("Add Working Blocks").fontWeight(.bold)}
.font(.title2)
.disabled(currants.curItem.count > 7)
以上视图的数据存储方式如下
struct CurItem: Codable, Identifiable {
var id = UUID()
var cunName: String
var curName: String
var curCode: String
var curSymbol: String
var curRate: Double
}
class Currants: ObservableObject {
@Published var curItem: [CurItem]
}
这是 class 和方法,我想在其中使用来自视图 manCurView
的计数
class BlockStatus: ObservableObject {
@EnvironmentObject var globalCur : Currants
@ObservedObject var netStatus : TestNetStatus = TestNetStatus()
func checkForUpdates() -> (Bool) {
if netStatus.connected == true {
if globalCur.curItem.count > 0 {
没有 minimal reproducible example 很难给你准确的代码,但你可以在你的 manCurView
中尝试类似下面的代码
@StateObject var blockStatus: BlockStatus = BlockStatus()
.onChange(of: currants.curItem.count, perform: { value in
print("send value from here")
blockStatus.arrayCount = value
})
并将下面的代码添加到 BlockStatus
@Published var arrayCount: Int = 0{
didSet{
//Call your method here
}
}
看下面的代码。
import SwiftUI
import Combine
struct CurItem: Codable, Identifiable {
var id = UUID()
}
class Currants: ObservableObject {
@Published var curItem: [CurItem] = [CurItem(), CurItem(), CurItem(), CurItem()]
}
class TestNetStatus: ObservableObject {
static let sharedInstance = TestNetStatus()
@Published var connected: Bool = false
init() {
//Simulate changes in connection
Timer.scheduledTimer(withTimeInterval: 10, repeats: true){ timer in
self.connected.toggle()
}
}
}
class BlockStatus: ObservableObject {
@Published var arrayCount: Int = 0{
didSet{
checkForUpdates()
}
}
@Published var checkedForUpdates: Bool = false
var netStatus : TestNetStatus = TestNetStatus.sharedInstance
//private var cancellable: AnyCancellable?
init() {
//Maybe? if you want to check upon init.
//checkForUpdates()
//Something like the code below is also possible but with 2 observed objects the other variable could be outdated
// cancellable = netStatus.objectWillChange.sink { [weak self] in
// self?.checkForUpdates()
// }
}
func checkForUpdates() {
if netStatus.connected == true {
if arrayCount > 0 {
checkedForUpdates = true
}else{
checkedForUpdates = false
}
}else{
checkedForUpdates = false
}
}
}
struct ManCurView: View {
@StateObject var currants: Currants = Currants()
@StateObject var blockStatus: BlockStatus = BlockStatus()
@StateObject var testNetStatus: TestNetStatus = TestNetStatus.sharedInstance
var body: some View {
List {
Text("checkedForUpdates = " + blockStatus.checkedForUpdates.description).foregroundColor(blockStatus.checkedForUpdates ? Color.green : Color.red)
Text("connected = " + blockStatus.netStatus.connected.description).foregroundColor(blockStatus.netStatus.connected ? Color.green : Color.red)
ForEach(currants.curItem, id: \.id) { item in
HStack {
Text(item.id.uuidString)
.frame(width: 100, alignment: .center)
Text(item.id.uuidString)
}
.font(.subheadline)
}
//Replaced with toolbar button for sample
//.onDelete(perform: removeItems)
//When the array count changes
.onChange(of: currants.curItem.count, perform: { value in
blockStatus.arrayCount = value
})
//Check when the networkStatus changes
.onChange(of: testNetStatus.connected, perform: { value in
//Check arrayCount
if blockStatus.arrayCount != currants.curItem.count{
blockStatus.arrayCount = currants.curItem.count
}else{
blockStatus.checkForUpdates()
}
})
}
.navigationBarTitle(Text("Manage Working Blocks"), displayMode: .inline)
//Replaced addCurView call with toolbar button for sample
.toolbar(content: {
ToolbarItem(placement: .navigationBarTrailing, content: {
Button("add-currant", action: {
currants.curItem.append(CurItem())
})
})
ToolbarItem(placement: .navigationBarLeading, content: {
Button("delete-currant", action: {
if currants.curItem.count > 0{
currants.curItem.removeFirst()
}
})
})
})
}
}
这是ContentView:注意在菜单中,因为这是一个视图,所以我可以直接使用计数来禁用条目输入。在 getData() 中,请注意我正在调用 blockStatus.checkForUpdates() 以确定是否可以调用 API。如果 currants.curItem.count = 0
将发生错误
我刚刚意识到从技术上讲 getData() 是 ContentView 的一部分,所以我可以将下面的调用更改为 if blockStatus.checkForUpdates() == true && currants.curItem.count != 0 {
我将花一些时间研究您上面的建议,看看我将来是否可以使用它。
非常感谢您对此的所有帮助。我不知道 Whosebug 上显示的代码建议。我一定会在未来遵循这些指导方针。盖伦
导入 SwiftUI
导入核心数据
导入组合
struct ContentView: View {
@EnvironmentObject var userData: UserData
@EnvironmentObject var currants: Currants
@EnvironmentObject var blockStatus: BlockStatus
var body: some View {
NavigationView {
VStack (alignment: .center) {
Text("Title")
.font(.title)
.fontWeight(.bold)
Spacer()
Group {
NavigationLink(destination: entryView()) {Text("Entry")}
.disabled(currants.curItem.count == 0)
Spacer()
NavigationLink(destination: totalView()) {Text("View Totals")}
Spacer()
NavigationLink(destination: listView()) {Text("View Entries")}
Spacer()
NavigationLink(destination: xchView()) {Text("View Dates")}
}
Rectangle()
.frame(height: 130)
.foregroundColor(Color.white)
}
.font(.title2)
.navigationBarItems(leading: NavigationLink (destination: settingsView()) {
Image(systemName: "gear")
.foregroundColor(.gray)
.font(.system(.title3))
}, trailing: NavigationLink( destination: aboutView()) {
Text("About")
})
.onAppear(perform: getData)
}
}
func getData() {
// check criteria for updating data once daily
if blockStatus.checkForUpdates() == true {
print(" doing update")
---- API HERE -----
}.resume()
}
}
}
我在使用视图中的条目数计数时遇到问题。我特别需要知道什么时候视图中没有条目。我在下面的视图中放置了调试代码,并且视图计数 currants.curItem.count
正在按预期更新。 checkForUpdates() 中的计数状态不符合上述视图。
如果我没记错的话,我应该只在视图中使用@EnvironmentObject 或@ObservedObject。我真的需要某种可以传递给方法 checkForUpdates 的全局变量。当 checkForUpdates() 中的计数为非零时,它会崩溃,而在视图中它实际上为零。它还在 checkForUpdates() 中崩溃,并出现错误 Fatal error: No ObservableObject of type Currencies found。作为此视图的祖先,货币的 View.environmentObject(_:) 可能缺失。
struct manCurView: View {
@EnvironmentObject var currants: Currants
var body: some View {
List {
ForEach(currants.curItem, id: \.id) { item in
HStack {
Text(item.curCode)
.frame(width: 100, alignment: .center)
Text(item.cunName)
}
.font(.subheadline)
}
.onDelete(perform: removeItems)
}
.navigationBarTitle(Text("Manage Working Blocks"), displayMode: .inline)
HStack {
NavigationLink(destination: addCurView()) {Text("Add Working Blocks").fontWeight(.bold)}
.font(.title2)
.disabled(currants.curItem.count > 7)
以上视图的数据存储方式如下
struct CurItem: Codable, Identifiable {
var id = UUID()
var cunName: String
var curName: String
var curCode: String
var curSymbol: String
var curRate: Double
}
class Currants: ObservableObject {
@Published var curItem: [CurItem]
}
这是 class 和方法,我想在其中使用来自视图 manCurView
的计数class BlockStatus: ObservableObject {
@EnvironmentObject var globalCur : Currants
@ObservedObject var netStatus : TestNetStatus = TestNetStatus()
func checkForUpdates() -> (Bool) {
if netStatus.connected == true {
if globalCur.curItem.count > 0 {
没有 minimal reproducible example 很难给你准确的代码,但你可以在你的 manCurView
@StateObject var blockStatus: BlockStatus = BlockStatus()
.onChange(of: currants.curItem.count, perform: { value in
print("send value from here")
blockStatus.arrayCount = value
})
并将下面的代码添加到 BlockStatus
@Published var arrayCount: Int = 0{
didSet{
//Call your method here
}
}
看下面的代码。
import SwiftUI
import Combine
struct CurItem: Codable, Identifiable {
var id = UUID()
}
class Currants: ObservableObject {
@Published var curItem: [CurItem] = [CurItem(), CurItem(), CurItem(), CurItem()]
}
class TestNetStatus: ObservableObject {
static let sharedInstance = TestNetStatus()
@Published var connected: Bool = false
init() {
//Simulate changes in connection
Timer.scheduledTimer(withTimeInterval: 10, repeats: true){ timer in
self.connected.toggle()
}
}
}
class BlockStatus: ObservableObject {
@Published var arrayCount: Int = 0{
didSet{
checkForUpdates()
}
}
@Published var checkedForUpdates: Bool = false
var netStatus : TestNetStatus = TestNetStatus.sharedInstance
//private var cancellable: AnyCancellable?
init() {
//Maybe? if you want to check upon init.
//checkForUpdates()
//Something like the code below is also possible but with 2 observed objects the other variable could be outdated
// cancellable = netStatus.objectWillChange.sink { [weak self] in
// self?.checkForUpdates()
// }
}
func checkForUpdates() {
if netStatus.connected == true {
if arrayCount > 0 {
checkedForUpdates = true
}else{
checkedForUpdates = false
}
}else{
checkedForUpdates = false
}
}
}
struct ManCurView: View {
@StateObject var currants: Currants = Currants()
@StateObject var blockStatus: BlockStatus = BlockStatus()
@StateObject var testNetStatus: TestNetStatus = TestNetStatus.sharedInstance
var body: some View {
List {
Text("checkedForUpdates = " + blockStatus.checkedForUpdates.description).foregroundColor(blockStatus.checkedForUpdates ? Color.green : Color.red)
Text("connected = " + blockStatus.netStatus.connected.description).foregroundColor(blockStatus.netStatus.connected ? Color.green : Color.red)
ForEach(currants.curItem, id: \.id) { item in
HStack {
Text(item.id.uuidString)
.frame(width: 100, alignment: .center)
Text(item.id.uuidString)
}
.font(.subheadline)
}
//Replaced with toolbar button for sample
//.onDelete(perform: removeItems)
//When the array count changes
.onChange(of: currants.curItem.count, perform: { value in
blockStatus.arrayCount = value
})
//Check when the networkStatus changes
.onChange(of: testNetStatus.connected, perform: { value in
//Check arrayCount
if blockStatus.arrayCount != currants.curItem.count{
blockStatus.arrayCount = currants.curItem.count
}else{
blockStatus.checkForUpdates()
}
})
}
.navigationBarTitle(Text("Manage Working Blocks"), displayMode: .inline)
//Replaced addCurView call with toolbar button for sample
.toolbar(content: {
ToolbarItem(placement: .navigationBarTrailing, content: {
Button("add-currant", action: {
currants.curItem.append(CurItem())
})
})
ToolbarItem(placement: .navigationBarLeading, content: {
Button("delete-currant", action: {
if currants.curItem.count > 0{
currants.curItem.removeFirst()
}
})
})
})
}
}
这是ContentView:注意在菜单中,因为这是一个视图,所以我可以直接使用计数来禁用条目输入。在 getData() 中,请注意我正在调用 blockStatus.checkForUpdates() 以确定是否可以调用 API。如果 currants.curItem.count = 0
将发生错误我刚刚意识到从技术上讲 getData() 是 ContentView 的一部分,所以我可以将下面的调用更改为 if blockStatus.checkForUpdates() == true && currants.curItem.count != 0 {
我将花一些时间研究您上面的建议,看看我将来是否可以使用它。
非常感谢您对此的所有帮助。我不知道 Whosebug 上显示的代码建议。我一定会在未来遵循这些指导方针。盖伦
导入 SwiftUI 导入核心数据 导入组合
struct ContentView: View {
@EnvironmentObject var userData: UserData
@EnvironmentObject var currants: Currants
@EnvironmentObject var blockStatus: BlockStatus
var body: some View {
NavigationView {
VStack (alignment: .center) {
Text("Title")
.font(.title)
.fontWeight(.bold)
Spacer()
Group {
NavigationLink(destination: entryView()) {Text("Entry")}
.disabled(currants.curItem.count == 0)
Spacer()
NavigationLink(destination: totalView()) {Text("View Totals")}
Spacer()
NavigationLink(destination: listView()) {Text("View Entries")}
Spacer()
NavigationLink(destination: xchView()) {Text("View Dates")}
}
Rectangle()
.frame(height: 130)
.foregroundColor(Color.white)
}
.font(.title2)
.navigationBarItems(leading: NavigationLink (destination: settingsView()) {
Image(systemName: "gear")
.foregroundColor(.gray)
.font(.system(.title3))
}, trailing: NavigationLink( destination: aboutView()) {
Text("About")
})
.onAppear(perform: getData)
}
}
func getData() {
// check criteria for updating data once daily
if blockStatus.checkForUpdates() == true {
print(" doing update")
---- API HERE -----
}.resume()
}
}
}