如果我的代码引用了视图,我可以将我的代码放在视图模型中吗?

Can I place my code in a viewmodel if that code has references to the view?

我有一个 view,其中包含很多逻辑代码,在 viewmodel 中会更好。问题是代码引用了 view,这意味着 viewmodel 需要来自 view 的对象才能正常工作。如果我正确理解 viewmodel 的概念,那么双向依赖会破坏 viewmodel

的全部目的

正如您从下面的代码中看到的那样,它包含行 addChild(x) 以及 .removeFromParent。因此,如果移动到 viewmodel,则代码必须类似于:mainView.addChild(x)。它确实有效,但我的问题是它是否合适。如果不是,我是否应该将代码保留在视图中,即使它占用了很多 space 并且其中有很多逻辑?

这些函数在原生touchDown()函数中使用:

func characterIsSelected(i: Int, j: Int) {
    //Check Accessibility of Tile
    if !gameBoardArray[i][j].isAccessibilityElement {
        hasBeenClickedOnce = true
        characterIsSelected = true
        characterVM.getGameBoardPosition().fillColor = SKColor.brown
        print("NOT ACCESSIBLE")
        return
    }else {
        print("Moving")
        viewModel.placeCharacter(row: i, col: j)
        buttonIsAvailable = false

        //SEE HERE
        guiButton.removeFromParent()
        enemyProximityCheck(i: i, j: j)
    }
}

func enemyProximityCheck(i: Int, j: Int){
    print("ENEMY PROXIMITY")
    //SCAN VICINITY OF CHARACTER. IF ENEMY IS ON TILE, GOTO COMBAT
    for ii in -1...1 {
        for jj in -1...1 {
            //gameBoardArray[i + (ii)][j + (jj)].fillColor = SKColor.blue
            if(i + (ii) < 0 || j + (jj) < 0 ) {
                print("LOW")
            }
            else if(i + (ii) > gameBoardArray.count - 1 || j + (jj) > gameBoardArray.count - 1) {
                print("HIGH")
            }
            else {
                if (gameBoardArray[i + (ii)][j + (jj)].contains(enemyVM.getCurrentEnemyPosition() ) ) {
                    print("AAARGH AN ENEMY!")

                    //SEE HERE
                    addChild(guiButton)
                    buttonIsAvailable = true
                    //enemyHasBeenSpotted = true
                }
            }
        }
    }//End for
}

如果您想成为 MVC 设计的纯粹主义者,那么游戏逻辑将进入 控制器,而不是视图 模型。他们的角色应该是:

  • model:游戏当前状态;例如哪些角色在哪些游戏板阵列槽中。它对视图或控制器一无所知。
  • view:游戏板的视觉表示。它从模型中读取,但不一定持有对它的引用。
  • 控制器:游戏逻辑。它通过更新模型并告诉视图根据模型重绘自身来响应用户操作。它对视图和模型有很强的引用。

就是说,如果您的游戏逻辑相当简单,那么将内容分离到模型、视图和控制器中可能就有些矫枉过正了。大多数时候,我从视图控制器 class 文件和情节提要中的相应视图控制器开始。如果它变得太复杂,那么我会创建一个视图 and/or 模型。视图控制器有一个到视图的出口,视图有到它的子视图的出口,视图的控件连接到视图控制器中的IBActions。

通常,如果您使用“视图模型”,视图模型通常不会直接操作视图。它会简单地将“遇到敌人”(或其他)事件传递给“视图”(我们中的许多人会认为它既是 UIView 层次结构又是视图控制器),然后负责相应地操纵视图。

不幸的是,根据您所概述的内容,很难准确地说出视图模型在您的情况下如何执行此操作。有些人宽松地使用术语“视图模型”,因此有几种可能的解释:

  1. 一种方法是让视图观察(通过某种“绑定”机制)视图模型中的某些 属性,当视图模型更新该状态时,视图将随后add/configure相应views/subviews相应。 (这 binding/observing 可以说是任何基于“视图模型”的方法的重要方面。)

  2. 其他方法包括视图模型的协议委托或闭包模式,以将 UI 更新传达给视图。 (这可以说更像是一种 MVP 方法,尽管我看到团队在这种情况下也使用术语“视图模型”。)

但一致的模式是视图模型通常不应进入并操纵视图层次结构本身。它应该简单地传达(一种或另一种方式)状态变化,“视图”将从那里接管它。

仅供参考,我认为 Medium iOS Architecture Patterns 在 iOS 应用程序的上下文中谈论这些不同的模式时很有启发性。