You need to enable JavaScript to run this app. 如何用Swift实现MySQL ID校验与多表更新并优化代码?
优惠活动
大模型
产品
解决方案
定价
更多

如何用Swift实现MySQL ID校验与多表更新并优化代码?

Swift 数据库更新类代码问题排查与优化方案

现存运行故障与逻辑缺陷

  • 主线程死循环阻塞:addToUserPlans 方法内的 while(bothChecked != 2){ print("waiting") } 是同步轮询逻辑。网络请求的回调运行在系统后台队列,主线程被这个死循环完全占用后,永远无法切回后台队列执行网络回调,bothChecked 计数器永远停在初始值0,App会直接卡死触发系统无响应弹窗。
  • 异步状态读取错位与竞态:类中定义的 UserPlanCheckIsGood、PlanCheckIsGood、bothChecked 是跨异步回调共享的可变实例属性,没有任何线程同步保护。当前调用流程是拿到合法planId后,同时并行触发 addPlan 和 addToUserPlans 两个方法:addPlan 被执行的瞬间,两个布尔校验属性还是初始值false,根本等不到 addToUserPlans 内部的校验流程完成,直接走入失败分支返回错误。就算时序巧合,两个方法交叉读写这些共享属性,读到的结果也是完全随机的。
  • 错误分支逻辑缺失:所有网络回调闭包中,触发失败回调后没有执行return跳出闭包,代码会继续向下执行,导致同一个completion闭包被多次调用,甚至用错误分支的残留状态走成功逻辑。比如getLowestPlanId接口请求失败时,回调了错误结果但没有return,后续仍然会用默认的lowestPlanId=2触发成功回调,完全吞掉了网络错误。
  • 强制解包崩溃隐患:网络返回的字符串经过裁剪后,直接用Int(jsonString)!强制转换为整数,一旦后端返回格式不符合预期,App会直接触发crash。
  • 计数器无重置机制:bothChecked 计数器没有在addToUserPlans方法入口做重置,第一次调用完成后值永远停在2,后续重复调用addToUserPlans会直接跳过校验流程,直接执行新增入库逻辑。
  • 流程逻辑割裂:两张表的新增操作本应共享同一次ID存在性校验结果,但当前代码把校验逻辑嵌在addToUserPlans内部,外部调用addPlan完全读取不到校验状态,整个流程被拆得零散混乱。

可运行版本核心调整点

  • 移除所有类层面的可变共享状态,所有流程的中间校验结果通过闭包在异步链路中传递,从根源上避免多线程读写竞态问题。
  • 删掉同步while轮询逻辑,改用GCD调度组实现两个ID校验任务的并行等待,不需要靠计数器硬等回调结果。
  • 补全所有错误分支的return逻辑,避免同一个回调被多次触发。
  • 把强制解包替换为安全类型转换,转换失败直接返回对应数据解析错误,杜绝crash。
  • 把原本并行乱序调用的两个新增方法,改成统一的串行异步链路:拿到合法planId → 并行完成所有表的ID存在性校验 → 校验全部通过后依次向三张表写入数据。

多表批量入库场景的规范实现思路

  • 所有多表关联的新增操作统一由后端接口完成数据库事务逻辑,客户端只需要触发一次写入请求,后端在数据库层面完成多表新增、失败自动回滚,避免客户端多次请求导致的部分表写入、部分表未写入的脏数据。
  • 全程不要依赖类实例存储的可变属性做异步流程的状态传递,所有中间值通过闭包参数逐段传递,杜绝多线程读写不同步的问题。
  • 所有网络回调统一切回主线程,避免触发UI更新时的线程安全问题。

内容的提问来源于stack exchange,提问作者Hubert Rzeminski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 16:36:03