ZIKViper
iOS VIPER implementation, demonstrating discovering modules and injecting dependencies with protocol. Provide VIPER code Templates.
Install / Use
/learn @Zuikyo/ZIKViperREADME
ZIKViper
iOS VIPER implementation, demonstrating discovering modules and injecting dependencies with protocol. Provide VIPER code Templates.
You can get answers about these discussions here:
- How to decouple modules thoroughly
- How to import a sub VIPER module
- How a sub module communicates with it's parent module
- How to inject dependencies to a module
- Interface-oriented router
两个iOS VIPER架构实现,关注于模块化和基于接口的依赖注入,并且提供快速生成VIPER代码的模板。
具体展示了以下问题的解决方案:
- 如何彻底地解决不同模块之间的耦合
- 如何在一个模块里引入子模块
- 子模块和父模块之间如何通信
- 如何对模块进行依赖注入
- 面向接口的路由工具
中文文档
Get Started
This repository uses submodule ZIKRouter, so you need to clone the submodule:
git clone --recursive https://github.com/Zuikyo/ZIKViper.git
Catalog
- What's VIPER
- Clean Architecture
- First Implementation: Thorough VIPER
- Decoupling
- Submodule
- Refactor MVC
- Second implementation: VIPER with ZIKRouter
- Demo and Templates
- Reference
<a name="VIPER-intro"></a>What's VIPER
The word VIPER is a backronym for:
- View
- Interactor
- Presenter
- Entity
- Router
A diagram for VIPER:

(from iOS Architecture Patterns: Demystifying MVC, MVP, MVVM and VIPER)
If it's new for you, check out these articles to learn VIPER architecture:
- MEET VIPER: MUTUAL MOBILE’S APPLICATION OF CLEAN ARCHITECTURE FOR IOS APPS
- Architecting iOS Apps with VIPER
- Brigade’s Experience Using an MVC Alternative: VIPER architecture for iOS applications
- VIPER to be or not to be?
- VIPER architecture: Our best practices to build an app like a boss
- The-Book-of-VIPER
<a name="Clean-Architecture"></a>Clean Architecture
Mutual mobile first came up with VIPER in 2013. VIPER is an application of Clean Architecture, so you have to know Clean Architecture before practicing VIPER.
Clean Architecture divides an app’s logical structure into distinct layers of responsibility. This makes it easier to isolate dependencies and to test the interactions at the boundaries between layers.
The diagram for Clean Architecture:

The key is the dependency rule:
The Dependency Rule
The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies.
The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in an inner circle. That includes, functions, classes. variables, or any other named software entity.
Those components in VIPER conform to this dependency rule.
<a name="implementation1"></a>First Implementation: Thorough VIPER
I will give two implementations of VIPER here. The first is a thoroughly decoupled implementation. Then I will show another implementation, an easier one allowing some coupling.
The thorough implementation describes dependency injection, module communication, module decoupling. I add some new components.
Below is the diagram. The color of the component is corresponding to their color in the diagram of Clean Architecture:

I will use a note app as sample.
<a name="implementation1-view"></a>View
View can be a UIView + UIViewController, or a custom UIView, or a Manager of UIView, as long as it implements the interface of View.
Responsibilities:
- Assemble different view widgets, and manage their layouts
- Provide
view inputinterface to presenter for updating view - Send view events to
eventHandler(thepresenter) - Get data for displaying views from
viewDataSource(thepresenter) - Provide
routeSourcetopresenteras the source view controller for navigation
View will import many widgets and implements their delegates. View will separate methods in these delegates into ViewEventHandlerInput and ViewDataSourceInput for different responsibilities.
viewDataSource and viewEventHandler stand for the two responsibilities of presenter for View.
Sample code:
@protocol ZIKNoteListViewEventHandler <NSObject>
- (void)handleDidSelectRowAtIndexPath:(NSIndexPath *)indexPath;
@end
@protocol ZIKNoteListViewDataSource <NSObject>
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
- (NSString *)textOfCellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSString *)detailTextOfCellForRowAtIndexPath:(NSIndexPath *)indexPath;
@end
@interface ZIKNoteListViewController () <UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) id<ZIKNoteListViewEventHandler> eventHandler;
@property (nonatomic, strong) id<ZIKNoteListViewDataSource> viewDataSource;
@property (weak, nonatomic) IBOutlet UITableView *noteListTableView;
@end
@implementation ZIKNoteListViewController
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
text:(NSString *)text
detailText:(NSString *)detailText {
UITableViewCell *cell = [self.noteListTableView dequeueReusableCellWithIdentifier:@"noteListCell" forIndexPath:indexPath];
cell.textLabel.text = text;
cell.detailTextLabel.text = detailText;
return cell;
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.viewDataSource numberOfRowsInSection:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *text = [self.viewDataSource textOfCellForRowAtIndexPath:indexPath];
NSString *detailText = [self.viewDataSource detailTextOfCellForRowAtIndexPath:indexPath];
UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath
text:text
detailText:detailText];
return cell;
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.eventHandler handleDidSelectRowAtIndexPath:indexPath];
}
@end
<a name="implementation1-presenter"></a>Presenter
Responsibilities:
- Handle view event, interpreting to wireframe or interactor
- Provide view dataSource from interactor to view
- Update view by interfaces in
ViewInput - Maintain states of view
- Call use cases provided by interactor
- Handle interactor event
- Provide datas of view from view to interactor
- Show other view modules by wireframe
Presenter is a transfer station between view and interactor. It transforms different events to business logic. You shouldn't import UIKit in presenter to affect rendering of view directly.
Sample code:
@interface ZIKNoteListViewPresenter ()<ZIKNoteListViewDataSource,ZIKNoteListViewEventHandler>
@property (nonatomic, strong) id<ZIKNoteListWireframeProtocol> wireframe;
@property (nonatomic, weak) id<ZIKViperView,ZIKNoteListViewProtocol> view;
@property (nonatomic, strong) id<ZIKNoteListInteractorInput> interactor;
@end
@implementation ZIKNoteListViewPresenter
#pragma mark ZIKNoteListViewDataSource
- (NSInteger)numberOfRowsInSection:(NSInteger)section {
return self.interactor.noteCount;
}
- (NSString *)textOfCellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *title = [self.interactor titleForNoteAtIndex:indexPath.row];
return title;
}
- (NSString *)detailTextOfCellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *content = [self.interactor contentForNoteAtIndex:indexPath.row];
return content;
}
#pragma mark ZIKNoteListViewEventHandler
- (void)handleDidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *uuid = [self.interactor noteUUIDAtIndex:indexPath.row];
NSString *title = [self.interactor noteTitleAtIndex:indexPath.row];
NSString *content = [self.interactor noteContentAtIndex:indexPath.row];
[self.wireframe pushEditorViewForEditingNoteWithUUID:uuid title:title content:content delegate:self];
}
@end
<a name
Related Skills
node-connect
345.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
106.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.9kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
