ios - 在iOS中实现VIPER架构

标签 ios viper-architecture

我第一次按照VIPER实现我的项目,我对其实现有一些疑问。这是我到目前为止所做的:
1)实现登录页面
步骤
i) 用户点击登录按钮(在 View Controller 上)。

ii)我有一个请求模型,其中存储“用户名”和“密码”。这是模型的结构:

struct Login{
    struct Request{
        var txt_email:String!
        var txt_password:String!
    }  
    struct Response {
        var homeData:Dictionary<String,Any>
    }
}

所以我将此请求对象传递给交互器。

iii)在Interactor中,我分配了不同的Workers(Worker类对象方法)来执行不同的任务,例如电子邮件验证,空文本字段验证等。如果一切顺利, Worker api 方法访问登录 API 并通过委托(delegate)将响应传递回 Interactor

iv)更新上述结构中的“响应”模型。

v) 现在我在 Interactor 中得到了响应,我将此响应传递给 Presenter 以根据 Controller 需要向用户显示的内容进行一些操作。

vi) 将数据传递给 Controller ,并将其呈现给用户。

问题1:我做的每件事都正确吗?如果不是,请告诉我正确的方法。如果是,请告诉我是否还有改进的空间。
问题2:我需要在主页上实现UITableViewUICollectionView,我认为扩展是实现的方法去争取他们。我也会对主页遵循相同的策略。但是假设,在 'didSelectRowAtIndexPath' 中,我需要向用户显示一个弹出窗口,我认为 ViewController 会更好直接向演示者询问数据。但是这是正确的方法吗?如果不是正确的方法是什么?
问题 3:我是否应该将数据从 cellForRowAtIndexPath: 传递到实际的 cell(MyCell:UITableViewCell) 类方法,然后将值分配给 UIElements?是还是否?

最佳答案

引用:https://medium.com/@javedmultani16/viper-architecture-viper-64f6cd91e6ec

我们开发人员基本上根据需求使用MVC、MVP或MVVM架构进行开发。选择哪种架构来开发应用程序很重要。影响软件架构选择的因素很多,如系统设计、需求、时间表等。

在 Viper 架构中,每个 block 对应一个具有特定任务、输入和输出的对象。它与装配线上的 worker 非常相似:一旦 worker 完成了对一个物体的工作,该物体就会被传递给下一个 worker ,直到产品完成。

V( View ): View 负责 UI 更新并显示演示者告诉它的任何内容。

I(Interactor):Interactor负责从模型层获取数据,其实现完全独立于用户界面。所有业务逻辑都写在Interactor内部。例如。获取在 Interactor 中编写的用户数据 API 调用。

P(演示者):演示者充当中介者的角色,它从交互中获取数据并将其传递给 View 。 (可能是数据或任何用户操作)

E(实体):基本上它包含交互器使用的对象模型。例如。学生、 friend 、大学等

R(路由器):它包含应用程序的导航逻辑。例如。下一个按钮操作显示第二个屏幕。

此外,我使用了协议(protocol),其中包含应用程序特定模块的所有规则和工作流程。在 iOS 中,所有协议(protocol)都写在每个模块的单独协议(protocol) swift 文件中。

此外,我使用了协议(protocol),其中包含应用程序特定模块的所有规则和工作流程。在 iOS 中,所有协议(protocol)都写在每个模块的单独协议(protocol) swift 文件中。

我们看一下它的文件结构: enter image description here

好处:

-所有模块都是独立的,因此 VIPER 非常适合大型团队。

-它使源代码更干净、更紧凑且可重用

-更容易采用TDD(测试驱动开发)

-您可以轻松地向现有应用程序添加新功能,而无需更改其他模块。

-它可以应用 SOLID 原则。

-减少合并冲突的数量。

-由于 UI 逻辑与业务逻辑分离,因此可以轻松编写自动化测试

struct Person { // Entity (usually more complex e.g. NSManagedObject)
    let firstName: String
    let lastName: String
}
struct GreetingData { // Transport data structure (not Entity)
    let greeting: String
    let subject: String
}
protocol GreetingProvider {
    func provideGreetingData()
}
protocol GreetingOutput: class {
    func receiveGreetingData(greetingData: GreetingData)
}
class GreetingInteractor : GreetingProvider {
weak var output: GreetingOutput!
func provideGreetingData() {
        let person = Person(firstName: "David", lastName: "Blaine") // usually comes from data access layer
let subject = person.firstName + " " + person.lastName
        let greeting = GreetingData(greeting: "Hello", subject: subject)
        self.output.receiveGreetingData(greeting)
   } 
}
protocol GreetingViewEventHandler {
    func didTapShowGreetingButton()
}
protocol GreetingView: class {
    func setGreeting(greeting: String)
}
class GreetingPresenter : GreetingOutput, GreetingViewEventHandler {
    weak var view: GreetingView!
    var greetingProvider: GreetingProvider!
func didTapShowGreetingButton() {
        self.greetingProvider.provideGreetingData()
}
func receiveGreetingData(greetingData: GreetingData) {
        let greeting = greetingData.greeting + " " + greetingData.subject
        self.view.setGreeting(greeting)
   }
 }
class GreetingViewController : UIViewController, GreetingView {
    var eventHandler: GreetingViewEventHandler!
    let showGreetingButton = UIButton()
let greetingLabel = UILabel()
override func viewDidLoad() {
 super.viewDidLoad()
 self.showGreetingButton.addTarget(self, action: "didTapButton:", forControlEvents:.TouchUpInside)

 }
func didTapButton(button: UIButton) {
        self.eventHandler.didTapShowGreetingButton()
}
func setGreeting(greeting: String) {
        self.greetingLabel.text = greeting
}
// layout code goes here
}
// Assembling of VIPER module, without Router
let view = GreetingViewController()
let presenter = GreetingPresenter()
let interactor = GreetingInteractor()
view.eventHandler = presenter
presenter.view = view
presenter.greetingProvider = interactor
interactor.output = presenter


关于ios - 在iOS中实现VIPER架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44796176/

相关文章:

ios - TableView (_ :viewforHeaderInSection:) Not Being Called

ios - Testflight SDK 和 iOS 模拟器 - 如何使用?

ios - 无法通过测试用例 iOS 将数据插入 sqlite 数据库

ios - iOS中模型、 View 和演示者的不同框架?

ios - 在具有 VIPER 架构的应用程序上更新 NSManagedObject

swift - 使用 VIPER 架构更新 View 中的标签

ios - React Native 中的 zIndex

ios - 无法从 CloudKit 仪表板中删除所有 'Users'

ios - VIPER 中 UITableView 委托(delegate)和数据源的实现

objective-c - 无法将数据发送到 VIPER 中的另一个模块