从主视图控制器中提取@IBOutlets属性值

时间:2018-10-15 16:51:19

标签: swift subclassing

从一开始,我就一直在使用MVP模型来保持运行,但是几个月后,我意识到我的大多数项目都具有“大型视图控制器”。扩展首先可以很好地整理实际的视图控制器文件,但从技术上讲,代码仍在视图控制器中。

在我的上一个项目中,我有一个更实用的方法是要进行应用内购买,然后用户才能解锁一些新功能。我们假设整个StoreKit逻辑都在工作,购买已成功完成,您即将向用户提供新功能。

为了解决这个问题,我在主视图控制器(func unlockFeatures)内有一个函数PreferencesViewController,当成功进行应用内购买时,该函数由观察者触发。

class PreferencesViewController: UIViewController {

    ...
    @obc func unlockFeatures {
        InAppPuchaseButton.isEnabled = false
        InAppPuchaseButton.applyOpacity(opacity: 1.0)
    }
    ...
}

在这一点上,当我只需要启用和更改单个按钮的不透明度时,一切看起来就很干净了。我的问题是当在func unlockFeatures内部需要处理多行UI代码时如何处理这种情况:

class PreferencesViewController: UIViewController {

    ...
    @obc func unlockFeatures {
        InAppPuchaseButton.isEnabled = false
        InAppPuchaseButton.applyOpacity(opacity: 1.0)
        InAppPuchaseButton.isHidden = false
        RefreshLabel.text = "DOWNLOADING EVENTS"
        self.activityIndicator.stopAnimating()
        //And keep going for 50 lines more of code!!
    }
    ...
}

对我来说,它看起来很混乱,我想在PreferencesViewController之外提取此函数,并在需要时调用它。有没有办法将所有这些UI逻辑提取到视图控制器类之外,或者这是一个不好的做法?

1 个答案:

答案 0 :(得分:1)

应用内购买示例就是一个很好的例子。我们在这里想要做的是提供一个集中的对象,该对象可以(例如):

  • 充当不涉及接口的IAP相关代码的所在地,例如充当SKPaymentTransactionObserver

  • 充当应用程序其余部分的网关,以便能够询问用户是否进行了购买(当然,我们的对象将通过咨询用户默认值来知道答案,但这将隐藏实现细节通过其公共API)

从视图控制器中断开这些功能很有意义,因为它们与控制任何视图无关。

因此,这是使用 helper类的绝佳机会。一个典型的实现是分配单例实例的类,我们可以获取该实例并将其存储在应用程序委托或根视图控制器的属性中,这两个实例都是持久的,可以从应用程序中的任何位置轻松访问。


在更广泛的背景下,我一直都使用这种帮助对象,以准确地解决您描述的问题。例如,在一个游戏应用中,我在主视图控制器中有一个 lot 代码,直到将几个操作区域划​​分为辅助类,因为它们与无关。控制视图。例如,计时器的逻辑和分数的维护变成了一个辅助对象。当我们进入游戏的下一阶段时,决定下一步做什么的“状态机”变成了一个辅助对象。依此类推。


在修改后的问题中,您说:

  

对我来说,它看起来很混乱,我想将此函数提取到PreferencesViewController之外,并在需要时调用它。有没有办法将所有这些UI逻辑提取到视图控制器类之外,或者这是一个不好的做法?

这里没有“杂乱无章”的东西;这是全部合一的功能,对。优良作法是在视图控制器类的内部 中使用UI操作,但也可以在其他地方调用(例如,通过我在回答中描述的助手)。实际上, I 要做的是让助手发布通知,以使它与将要发生的事情无关。它只是喊“好,用户已购买!”然后视图控制器接收到通知并调用该方法。