Swift调用函数时Delegate变量始终为nil的问题排查
问题:调用
reconcile()时selectedTransaction始终为nil 我实现了Delegate模式处理对账逻辑,但调用reconcile()函数时selectedTransaction始终返回nil。子视图的onChange回调中能正确打印选中的交易数据,但父视图通过按钮触发调用时,该值就变成了nil。
相关代码如下:
Delegate实现类
class MatchReconciliationViewState: ReconciliationDelegate { var selectedTransaction: Transaction? let statementLine: StatementLine init(selectedTransaction: Transaction? = nil, statementLine: StatementLine) { self.selectedTransaction = selectedTransaction self.statementLine = statementLine } func canReconcile() -> Bool { return nil != selectedTransaction } func reconcile() { print("reconcile: \(String(describing: selectedTransaction))") guard let selectedTransaction = selectedTransaction else { return } ReconciliationFunctions.match(statementLine: statementLine, toTransaction: selectedTransaction) } }
子视图onChange回调(数据持有正常)
.onChange(of: selectedTransaction) { newValue in print("onChange: \(String(describing: selectedTransaction))") reconciliationDelegate.selectedTransaction = newValue parentState.canReconcile = reconciliationDelegate.canReconcile() print("onChangeDelegate: \(String(describing: reconciliationDelegate.selectedTransaction))") }
父视图触发代码(调用时selectedTransaction为nil)
private func reconcileStatementLine() { print("delegate: \(String(describing: state.reconciliationDeleage))") state.reconciliationDeleage?.reconcile() // persistence.commit() // presentationMode.wrappedValue.dismiss() }
协议定义
public protocol ReconciliationDelegate: AnyObject { func canReconcile() -> Bool func reconcile() }
父视图及状态类
// 父视图代码 @StateObject var state: ReconciliationViewState var body: some View { Button(action: reconcileStatementLine) { Text("Reconcile") } } private func reconcileStatementLine() { print("delegate: \(String(describing: state.reconciliationDeleage))") state.reconciliationDeleage?.reconcile() // persistence.commit() // presentationMode.wrappedValue.dismiss() }
// 持有Delegate的状态类 class ReconciliationViewState: ObservableObject { var reconciliationDeleage: ReconciliationDelegate? = nil }
问题原因及解决方案
核心问题:拼写错误+实例不统一
- 致命拼写错误:代码中存在属性名拼写不一致——
reconciliationDeleage(少了一个字母t)和reconciliationDelegate。这直接导致父视图操作的Delegate属性,和子视图中修改的Delegate属性不是同一个,自然无法同步数据。 - 实例不共享:如果子视图和父视图使用的是不同的
MatchReconciliationViewState实例,即使拼写正确,也会出现数据不同步的情况。
修复步骤
统一属性名拼写
把所有reconciliationDeleage修正为reconciliationDelegate:- 修正状态类:
class ReconciliationViewState: ObservableObject { var reconciliationDelegate: ReconciliationDelegate? = nil } - 修正父视图调用代码:
private func reconcileStatementLine() { print("delegate: \(String(describing: state.reconciliationDelegate))") state.reconciliationDelegate?.reconcile() }
- 修正状态类:
确保Delegate实例唯一共享
在初始化子视图时,直接传入父视图状态中的reconciliationDelegate实例,避免创建新的对象:ChildView( reconciliationDelegate: state.reconciliationDelegate, parentState: state )提前初始化Delegate实例
在ReconciliationViewState的初始化方法中创建Delegate实例,确保使用前已存在:class ReconciliationViewState: ObservableObject { var reconciliationDelegate: ReconciliationDelegate? init(statementLine: StatementLine) { self.reconciliationDelegate = MatchReconciliationViewState(statementLine: statementLine) } }
验证要点
修复后,可通过以下方式确认问题解决:
- 打印
state.reconciliationDelegate和子视图的reconciliationDelegate内存地址,确认是同一个实例 - 子视图选中交易后,打印
state.reconciliationDelegate?.selectedTransaction,确认值已同步 - 点击父视图按钮时,
reconcile()方法中打印的selectedTransaction不为nil
内容的提问来源于stack exchange,提问作者LostBalloon
相关产品推荐
相关产品推荐

