VIPER-Application中的界面层被用来创建和展示视图控制器以及控制器转换。一个VIPERS应用使用遵从WireframeProtocol的对象在应用中的控制器之间路由。
它是将您的应用中视图控制器连接在一起的有力工具。它接收一个NSURL和一些参数,与创建视图控制器的组件(ControllerProvider)通信,这些组件创建与该URL连接的视图控制器,并将其传递给那些负责展示控制器(ControllerRoutingPresenter)的组件。
界面层负责导航到下一个视图控制器并通讯连接界面层中的所有对象。它用于引入层以导航到下一个视图控制器。我们建议您不要在位于视图层的视图控制器中使用它。最好通过代理调用它。
VIPER是应用于移动应用的架构。您可以在以下链接中找到一些解释:objc.io博客文章(例子是用OBJ-C编写的,但我相信您会接受这个挑战:-P)
一个负责为特定URL创建视图控制器的提供类
示例
class ExampleControllerProvider : ControllerProviderProtocol {
let responsibleForRoutesCreatedWithRouteString = "/path/to/my/controller"
func controller( forRouteString : String,
option: RoutingOptionProtocol,
parameters: [String:AnyObject]) -> UIViewController?{
if(forRouteString == self.responsibleForRoutesCreatedWithRouteString){
return UIViewController()
}else{
return nil
}
}
}
// somewhere in your application (appdelegate or a factory could be a good idea)
// add provider to wireframe
let myProvider = ExampleControllerProvider()
wireframe.addControllerProvider(provider:myProvider)
//route to controller and present it
wireframe.routeURL( URL: NSURL(string:"/path/to/my/controller"),
parameters: nil,
option: RoutingOptionPush())
路由选项指定了控制器展示的方式。您可以创建新的路由选项以实现新方式展示视图控制器。它更像是一个消息对象到特定的ControllerRoutingPresenter,它聚集展示控制器所需的必要信息。
您可以在ControllerRoutingPresenter部分找到一个完整的示例。
路由选项提供者负责为特定URL创建一个路由选项。通过为URL创建特定的路由选项,路由选项提供者可以决定控制器应该如何展示。
示例
class ExampleRoutingOptionsProvider : RoutingOptionProviderProtocol {
let responsibleForRoutesCreatedWithRouteString = "/path/to/my/controller"
func options( forRoutingString: String,
parameters: [String,NSObject],
currentOption: RoutingOptionProtocol?) -> RoutingOptionProtocol?{
// if someone has already created a routing option, use that
// (don't override it if this is not nessecary!)
if let currentRoutingOption = currentOption{
return currentRoutingOption
}else{
//create a new object conforming to RoutingOptionProtocol otherwise
return RoutingOptionPush()
}
}
}
// somewhere in your application (appdelegate or a factory could be a good idea)
// add provider to wireframe
let myProvider = ExampleRoutingOptionsProvider()
wireframe.addRoutingProvider(provider:myProvider)
//
// I suppose that you added a controller provider for your
// route somewhere
//
//route to controller and push it
wireframe.routeURL( URL: NSURL(string:"/path/to/my/controller"),
parameters: nil,
option: nil)
一个负责使用特定路由选项展示控制器的展示者。
示例
//create a new routing option for pushing with a hidden navigation bar
struct HiddenNavbarRoutingOption : RoutingOptionPushProtocol{
let animated : bool
}
//create a new controller routing presenter for your option
class HiddenNavBarRoutingPresenter : ControllerRoutingPresenterProtocol{
let navigationController : UINavigationController
init(navigationController : UINavigationController){
self.navigationController = navigationController
}
func isResponsible(option:RoutingOptionProtocol) -> Bool{
return option is HiddenNavbarRoutingOption
}
func present(routeString: String,
controller: UIViewController,
option: RoutingOptionProtocol,
parameters : [String : AnyObject],
wireframe : WireframeProtocol,
completion: ((routeString : String,
controller : UIViewController,
option : RoutingOptionProtocol,
parameters : [String : AnyObject],
wireframe : WireframeProtocol)->Void)){
self.navigationController.setNavigationBarHidden(true, animated: option.animated)
CATransaction.begin()
CATransaction.setCompletionBlock {
completion( routeString : routeString,
controller : controller,
option : option,
parameters : parameters,
wireframe : wireframe)
}
navigationController.pushViewController(controller, animated: true)
CATransaction.commit()
}
}
// somewhere in your application (appdelegate or a factory could be a good idea)
// add presenter to wireframe
let myPresenter = HiddenNavBarRoutingPresenter(myNavigationController)
wireframe.addControllerRoutingPresenter(presenter)
//
// I suppose that you added a controller provider for your
// route somewhere
//
//route to controller and present it
wireframe.routeURL( URL: NSURL(string:"/path/to/my/controller"),
parameters: nil,
option: HiddenNavbarRoutingOption(animated : true))
一个用于观察路由过程的观察者对象。它可以在返回NSURL并调用shouldRouteTo方法时拦截并重定向你的路由请求。
在未登录时重定向的示例
//
// lets assume you have a fancy class named LoginManager which tells you
// if you are logged in for a specific url
//
//
// Create routing observer
//
class AuthRoutingObserver : RoutingObserverProtocol{
let loginManager : LoginManager
init(loginManager : LoginManager){
self.loginManager = loginManager
}
func observes(routeString: String,
option: RoutingOptionProtocol,
parameters: [String : AnyObject])->Bool{
return true
}
func shouldRouteTo(routeString: String,
option: RoutingOptionProtocol,
parameters: [String : AnyObject]) -> NSURL?{
if(loginManager.allowsRoutingForRouteString(routeString)){
return nil
}else{
return NSURL("/path/to/access/denied/controller")
}
}
func didRouteTo( controller: UIViewController,
routeString: String,
option: RoutingOptionProtocol,
parameters: [String : AnyObject],
routingPresenter: ControllerRoutingPresenterProtocol,
wireframe: WireframeProtocol) -> Void{
//do something after the controller of this route is visible in your app
}
}
// somewhere in your application (appdelegate or a factory could be a good idea)
// add presenter to wireframe
let authObserver = AuthRoutingObserver(myLoginManager)
wireframe.addRoutingObserver(authObserver)
// routes to "/path/to/access/denied/controller"
// when not logged in
wireframe.routeURL(NSURL(string: "/a/route/which/needs/login"))
// works as expected
wireframe.routeURL(NSURL(string: "/a/route/which/does/not/need/login"))
要运行示例项目,请先克隆仓库,然后从示例目录运行pod install
。
可以通过CocoaPods获取VISPERS-Wireframe-Protocol。要安装它,只需将以下行添加到你的Podfile中
pod "VISPERS-Wireframe-Protocol"
Jan Bartel, [email protected]
VISPERS-Wireframe-Protocol遵循MIT许可。有关更多信息,请参阅LICENSE文件。