Swift:ViewModel 应该是结构体还是类?

2024-04-29

我正在尝试在我的新项目中使用 MVVM 模式。第一次,我创建了所有的视图模型来构建。但是,当我使用闭包实现异步业务逻辑(例如 fetchDataFromNetwork)时,闭包捕获旧视图模型值,然后更新为该值。不是新的视图模型值。

这是操场上的测试代码。

import Foundation
import XCPlayground

struct ViewModel {
  var data: Int = 0

  mutating func fetchData(completion:()->()) {
    XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
      result in
      self.data = 10
      print("viewModel.data in fetchResponse : \(self.data)")
      completion()
      XCPlaygroundPage.currentPage.finishExecution()
      }.resume()
  }
}

class ViewController {
  var viewModel: ViewModel = ViewModel() {
    didSet {
      print("viewModel.data in didSet : \(viewModel.data)")
    }
  }

  func changeViewModelStruct() {
    print("viewModel.data before fetch : \(viewModel.data)")

    viewModel.fetchData {
      print("viewModel.data after fetch : \(self.viewModel.data)")
    }
  }
}

var c = ViewController()
c.changeViewModelStruct()

控制台打印

viewModel.data before fetch : 0
viewModel.data in didSet : 0
viewModel.data in fetchResponse : 10
viewModel.data after fetch : 0

问题是 ViewController 中的视图模型没有新的值 10。

如果我将 ViewModel 更改为类,则不会调用 didSet,但 ViewController 中的视图模型具有新值 10。


你应该使用一个类。

如果您使用带有变异函数的结构,则该函数不应在闭包内执行变异;你应该not请执行下列操作:

struct ViewModel {
  var data: Int = 0

  mutating func myFunc() {
      funcWithClosure() {
          self.data = 1
      }
  }
}

如果我将 ViewModel 更改为类,则不会调用 didSet

这里没有任何问题 - 这是预期的行为。


如果您喜欢使用struct, 你可以做

  func fetchData(completion: ViewModel ->()) {
    XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
      result in
      var newViewModel = self
      newViewModel.data = 10
      print("viewModel.data in fetchResponse : \(self.data)")
      completion(newViewModel)
      XCPlaygroundPage.currentPage.finishExecution()
      }.resume()
  }


  viewModel.fetchData { newViewModel in
     self.viewModal = newViewModel
      print("viewModel.data after fetch : \(self.viewModel.data)")
    }

另请注意,关闭提供给dataTaskWithURL不在主线程上运行。您可能想打电话dispatch_async(dispatch_get_main_queue()) {...} in it.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift:ViewModel 应该是结构体还是类? 的相关文章

  • 快速布尔运算

    这实在令人困惑 有人有什么想法吗 let viewHasMovedToRight false initially I want this to be false then func moveViewToRight sender UIButt
  • OSX Swift 在默认浏览器中打开 URL

    如何使用 Swift 作为编程语言和 OSX 作为平台在系统默认浏览器中打开 URL 我发现了很多UIApplication like UIApplication sharedApplication openURL NSURL string
  • 数组的扩展,其中元素是可选的

    我有一个数组String like so var myArray String 2 banana nil 31 我还有另一个数组String像这样 var myStringArray String 2 3 我为 Array 编写了一个扩展
  • 如何让应用更新以吸引人的屏幕形式提供给用户? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我最近在使用 Make My Trip 应用程序 我发现每当我启动应用程序时都会出现一个非常有吸引力的应用程序更新弹出屏幕 它说要更新应用程
  • iOS 视频压缩 Swift iOS 8 损坏的视频文件

    我正在尝试压缩用户相机从 UIImagePickerController 拍摄的视频 不是现有视频 而是动态视频 以上传到我的服务器 并花费少量时间来完成此操作 因此较小的尺寸是理想的选择 而不是 30 较新质量的相机为 45 mb 这是在
  • Swift Firebase - 如何在使用 queryOrdered(byChild: ).queryEqual(toValue: ) 时获取所有 k/v

    root reviews postABC postId reviewXYZ I want everything under this reviewUID buyerUID 01010 text fast shipping responseT
  • 无法在 Swift 中创建文件路径

    我尝试在 Swift 中打开该文件 为此 我创建了文件路径 这不起作用 maaaacy pwd Users tsypa maaaacy cat a txt test maaaacy a swift nil maaaacy 剧本 usr bi
  • 使用 Metal 高效计算 UIImage/CIImage 中有多少透明像素

    我们可以计算有多少个透明像素的最快方法是什么CIImage UIImage 例如 如果我们谈论效率 我的第一个想法是使用Metal Kernel使用任一CIColorKernel左右 但我不明白如何使用它来输出 计数 我还有其他想法 使用某
  • 在 SwiftUI 中,如何执行手势但将手势转发到其后面的视图?

    我正在创建一个工具提示系统 如果用户触摸工具提示之外的任何地方 我想关闭工具提示 我希望这样在工具提示之外的触摸既可以消除工具提示 又可以激活用户点击的任何控件 因此 您可以打开一个工具提示 然后仍然单击工具提示外部的按钮 并在第一次点击时
  • 使用 Swift 创建 NSAlert

    我有在 Objective C 中创建和 NSAlert 的代码 但我现在想在 Swift 中创建它 该警报旨在确认用户想要删除文档 我想要 删除 按钮来运行删除功能 而 取消 按钮只是为了消除警报 我怎样才能用 Swift 写这个 NSA
  • 在 Firebase 中为 TextView Swift 保存字体和大小的方法是什么

    我想在 Firebase 中保存 Swift 中 TextView 的字体 大小和对齐方式 这样我就可以在另一个视图中调用它 我只能将颜色保存在 Firebase 中 这是显示我是如何做到的的代码 IBAction func SendBtn
  • 如何在 Safari 上打开本地 html 文件?

    我想打开本地 html 文件Safari集成到我的Swift 3应用 我知道如何使用网址来做到这一点 这是我用来执行此操作的代码 let encodedString url addingPercentEncoding withAllowed
  • 如何使用 Google 的 GithubBrowserSample 方法在片段之间共享视图模型?

    我对 Android 架构组件的使用非常陌生 因此我决定使用 GithubBrowserSample 来构建我的应用程序来实现我的许多用例 但我有一个问题 我不知道使用这种方法在片段之间共享视图模型的正确方法是什么 我想共享视图模型 因为我
  • SwiftUI - 从 NSObject 继承的 ObservableObject 在 iOS 13 中不会更新

    我知道 这是 无法在 iOS XX 中工作 问题之一 但我完全陷入困境 所以我有一个ObservableObject继承自的类NSObject 因为我需要听委托方法UISearchResultsUpdating class SearchBa
  • skView.ignoreSiblingOrder 在 swift 中的重要性/效率?

    这样做有多重要 高效skView ignoreSiblingOrder true初始化场景时 现在 我将其设置为 true 但由于某种原因 当我从 MainMenu 场景启动 GameScene 时 它 会在我的角色之前加载背景 即使背景的
  • 在 AngularJS 中设置应用程序范围的 HTTP 标头

    有没有办法设置 httpProvider标题之外angular module myApp config 登录用户后 我从服务器获取身份验证令牌 我需要将其作为 HTTP 标头添加到所有后续请求中 您可以使用角度的默认标题1 0 x http
  • 在 MVVM 中设置可见性的最佳方法

    In my View我有三个对象 其中一个在任何给定时间都是可见的 在我的Model我有一个枚举来代表这三个状态 我应该如何实施我的ViewModel a 为每个对象的可见性创建一个布尔值 并将每个对象绑定到该布尔值 使用 bool gt
  • typedef 结构体指针定义

    我对 C 很陌生 并且对所有指针的东西都有一些问题 我写了这段代码 typedef struct edgeitem double weight EDGE ITEM pEDGE ITEM also declaration of a point
  • ios Vision VNImageRequestHandler方向问题

    我正在尝试使用相机通过相机检测脸部VNImageRequestHandler iOS 愿景 当我在横向模式下用相机指向照片时 它会检测到面部 但方向模式相反 let detectFaceRequestHandler VNImageReque
  • 使用prepareForSegue传递数据

    我试图将数据从viewController 1传递到viewController2 我有2个按钮和1个segue 因此有一个segue标识符 这2个按钮 按下时每个按钮应显示 1个标签用于显示标题 1个textView用于显示定义 我很难显

随机推荐

  • 如果 Django 中的表单字段与 Python 关键字同名,如何声明该字段?

    我在 Django 中有一个简单的表单 看起来像这样 class SearchForm forms Form text forms CharField from forms DateField until forms DateField 失
  • 如何在fetch-mock中模拟多个获取?

    我正在测试我的反应组件 我想模拟几个get运营 我想做的是这样的 test Created correctly async gt fetchMock get JSON stringify FIRSTGETOBJ fetchMock get
  • 如何在 Robot Framework 中将变量定义为具有列表值的字典

    在我的一个测试用例中 我需要定义一个字典 其中键是字符串 值是字符串数组 我怎样才能在机器人框架中做到这一点 我第一次尝试使用如下所示的构造 但行不通 Variables Dictionary A StringA1 StringA2 B S
  • 显示 Presto 中所有模式的表

    急速 SHOW SCHEMAS 返回所有模式 SHOW TABLES FROM foo 返回 foo 模式的所有表 有没有一种简单的方法可以从 Presto 中的所有模式返回表 您可以使用select table schema table
  • Google Chrome 扩展:如何在以编程方式注入的内容脚本中包含 jQuery?

    我正在注射我的内容脚本来自背景页当用户点击浏览器动作按钮 就像这样 chrome browserAction onClicked addListener function tab chrome tabs executeScript null
  • 有没有 SwiftUI 方法来制作文本上标或下标?

    我知道可以像这样应用偏移量Text TM offset x 0 y 7 但是有没有不同或更好的方法来在 SwiftUI 中创建一些上标或下标文本 这是使用的通用方法 baselineOffset Text Company font call
  • 将 Boolean FlatZinc 转换为 CNF DIMACS

    为了解决一个布尔方程组 http arxiv org abs 1108 2830 我正在尝试Constraint Programming Solver MiniZinc http www minizinc org 使用以下输入 Solve
  • 以编程方式设置 Outlook 2013 签名默认值?

    是否可以通过编程方式设置 Outlook 2013 默认签名设置 我们可以生成用户的签名 但还想将签名设置为默认显示在用户的电子邮件中 该设置本身似乎隐藏在 Outlook 配置文件下的注册表中 HKEY CURRENT USER Soft
  • 如何在真实设备上模拟来电? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 出于测试目的 我想在真实的 Andr
  • 错误:找不到模块“@discordjs/opus”

    每次我运行不和谐的语音识别代码时 它都会上线 但一旦加入频道 我的代码就会显示错误 找不到模块 discordjs opus Require stack C Users SURYASH Desktop DiscordSpeechBot no
  • Google 地图 v3 - 我能否确保每次都能顺利平移?

    我的地图在一座城市内有数百个标记 通常不超过 20 英里半径 我已通读文档 但尚未找到一种方法来将 init 设置为在每个标记之间自动平移 无论距离如何 默认行为是如果靠近则平移 如果远则跳跃 我理解他们为什么要这样做 因为地图不会在选定的
  • 使用 ggplot2 表示散点图中每个点的小饼图

    我想创建一个散点图 其中每个点都是一个小饼图 例如考虑以下数据 foo lt data frame X runif 30 Y runif 30 A runif 30 B runif 30 C runif 30 下面的代码将绘制一个散点图 代
  • 尽管有 FOLLOWLOCATION,但仍使用 cURL 获取 301

    尽管使用了 FOLLOWLOCATION 和 MAXREDIRS 我还是收到了 301 错误 我不知道该怎么做 我尝试了一切我能做的 HEADER为0 FOLLOWLOCATION为1 MAXREDIRS为30 多次更改USERAGENT
  • 如何在MVVM架构中将animationview play与LottieForms绑定?

    所以我在列表视图中处理动画 并且我想随时播放一次 所以我想控制它 这是图书馆https github com martijn00 LottieXamarin https github com martijn00 LottieXamarin
  • 在 CAKeyFrameAnimation 期间检测碰撞

    当一个 UIImageView 在 CAKeyFrameAnimation 期间沿一条路径行进时 是否可以检测到两个 UIImageView 的碰撞 如果是这样 这是如何完成的 我尝试了多种方法 包括在动画期间检查 CGRect 是否发生碰
  • 如何删除我的产品中未使用的 CSS 类?

    我只想删除我的产品中未使用的 CSS 类 它不是 HTML 文件 它有 jsp XML 和 js 文件 我的产品中有很多未使用的类 手动删除它们需要很长时间 Dust Me 选择器 http www sitepoint com dustme
  • 什么触发了java垃圾收集器

    我对 Java 中垃圾收集的工作原理有点困惑 我知道当不再有对某个对象的实时引用时 该对象就有资格进行垃圾回收 但是如果它有对实时对象的引用怎么办 可以说我有一个节点集合 它们再次引用更多节点 List 1 gt Node a gt Nod
  • 在轮询 SCM 时将 ssh-agent 与 jenkins 结合使用

    我使用 Jenkins ssh agent 插件来为我的构建提供 ssh 凭证 该凭证运行良好 但是我将其设置为轮询 scm 在本例中为 bitbucket git 以检查更改 当然 要访问存储库以轮询更改 它还需要这些 ssh 凭据 我似
  • ios 如何为文本字段添加底部边框和侧面设计

    我想添加底部边框 如下图所示 我已成功添加底线 但我没有得到侧面小线 这是我的代码 CALayer border CALayer layer CGFloat borderWidth 1 border borderColor UIColor
  • Swift:ViewModel 应该是结构体还是类?

    我正在尝试在我的新项目中使用 MVVM 模式 第一次 我创建了所有的视图模型来构建 但是 当我使用闭包实现异步业务逻辑 例如 fetchDataFromNetwork 时 闭包捕获旧视图模型值 然后更新为该值 不是新的视图模型值 这是操场上