在iOS中实现VIPER架构

时间:2017-06-28 07:29:20

标签: ios viper-architecture

我是第一次根据 VIPER 实施我的项目,我对它的实施有一些疑问。这是我到目前为止所做的: 1)实施登录页面
STEPS
i)用户点击登录按钮(在视图控制器上)。

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

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

所以我将此Request对象传递给 Interactor。

iii)在 Interactor 中,我分配了不同的 Workers(工人类对象方法)来执行不同的任务,例如电子邮件验证,空文本域验证等。如果一切顺利, worker api方法命中登录API并通过委托将响应传递回 Interactor iv)更新上述结构中的“响应”模型。

v)现在我在 Interactor 中有响应,我将此响应传递给 Presenter ,根据控制器需要向用户显示的内容进行一些操作。

vi)将数据传递给控制器并将其呈现给用户。

问题1:我做得对不对。如果没有,请告诉我正确的方法。如果是,请告诉我是否还有改进的余地。
问题2:我需要在主页上实现 UITableView UICollectionView ,我认为扩展是通往他们也会遵循相同的主页策略。但是,假设在'didSelectRowAtIndexPath'中,我需要向用户显示弹出窗口,我认为 ViewController 会更好直接询问 Presenter 有关数据的信息。但这是正确的方法吗?如果没有正确的方法?
问题3:我应该将 cellForRowAtIndexPath:中的数据传递给实际的单元格(MyCell:UITableViewCell)类方法,然后将值分配给UIElements吗?是或否?

2 个答案:

答案 0 :(得分:0)

关于问题2和问题3,这里是我使用UITableViewhttps://stackoverflow.com/a/45709546/3990005的简单Viper应用示例的答案。

ViewController 不与 Interactor 对话,但对于演示者,在cellForRowAtIndexPath:上您应该使用 Presenter 已选择IndexPath的信息。

关于单元格创建,我喜欢在UITableViewCell类中使用设置方法,在 ViewController 中请求 Presenter 获取数据并将其传递给细胞。其中一些在上面的示例中可见,这里是单元格的setupCell方法:

func setupCell(withSong: song) {
    titleLabel.text = song.title
    descriptionLabel.text = song.description
}

答案 1 :(得分:0)

参考:https://medium.com/@javedmultani16/viper-architecture-viper-64f6cd91e6ec

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

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

V(视图):视图负责UI更新,并显示演示者告诉的内容。

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

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

E(实体):基本上,它包含Interactor使用的对象模型。例如。学生,朋友,学院等。

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

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

此外,我使用了PROTOCOL,该协议包含应用程序特定模块的所有规则和工作流程。在iOS中,每个模块的所有协议都写入单独的协议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