如何将视图条目计数传输到类方法
Posted
技术标签:
【中文标题】如何将视图条目计数传输到类方法【英文标题】:How to Transmit a View Entry Count to a Class Method 【发布时间】:2021-01-08 00:37:31 【问题描述】:我在使用视图中的条目数计数时遇到问题。我特别需要知道视图中什么时候没有条目。我已将调试代码放在下面的视图中,并且视图计数 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]
这是我想从视图 manCurView 中使用 count 的类和方法
class BlockStatus: ObservableObject
@EnvironmentObject var globalCur : Currants
@ObservedObject var netStatus : TestNetStatus = TestNetStatus()
func checkForUpdates() -> (Bool)
if netStatus.connected == true
if globalCur.curItem.count > 0
【问题讨论】:
【参考方案1】:如果没有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()
)
)
)
【讨论】:
Lorem:我向 manCurView 添加了@StateObject 和 .onChange 逻辑。我收到类型'RateStatus'的错误没有成员'onChange'并且不能在属性初始化程序中使用实例成员'currants';属性初始化程序在 'self' 可用之前运行。 checkForUpdates 在调用 API 之前被调用——我不能从 didSet 调用它。如果 manCurView 计数为 0,我无法调用 APIRateStatus
上没有示例代码,所以除了 .onChange
是从 View
的 body
调用的 SwiftUI 方法之外,我无法对此发表评论。就像我之前说的,没有最小的可复制产品;我可以复制和粘贴并查看所有内容;我无法具体帮助你。在单独的项目中创建具有相同功能的示例代码,并且所有代码都应该在同一个文件中。
看看上面的代码,你可以看到一个例子【参考方案2】:
这里是 ContentView:在菜单中注意,因为这是一个视图,我可以直接使用 count 来禁用条目输入。在 getData() 中,请注意我正在调用 blockStatus.checkForUpdates() 以确定是否可以调用 API。如果 currants.curItem.count = 0 则会发生故障
我刚刚意识到从技术上讲 getData() 是 ContentView 的一部分,因此我可以将下面的调用更改为 if blockStatus.checkForUpdates() == true && currants.curItem.count != 0
我将花一些时间研究您上面的建议,看看我将来是否可以使用它。
感谢您对此的所有帮助。我不知道 *** 上显示的代码建议。我一定会在未来遵循这些准则。盖伦
导入 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()
【讨论】:
以上是关于如何将视图条目计数传输到类方法的主要内容,如果未能解决你的问题,请参考以下文章