Skip to content

Latest commit

 

History

History
168 lines (100 loc) · 7.51 KB

FAQ.md

File metadata and controls

168 lines (100 loc) · 7.51 KB

FAQ

Should all protocols be put in a public module?

Centrally putting all routable protocols in a public module is the most direct way to provide them. But it's not easy to maintain them. And you may import those unused protocols.

Protocols used by ZIKRouter are explicitly declared as routable. You can use multi protocols for a same module. So those protocols can be managed discretely. Then you don't have to put them in a same public module.

How to get all routable protocols?

Protocols are all declared in headers. You can search these declaration code:

extension RoutableView where Protocol ==

extension RoutableViewModule where Protocol ==

extension RoutableService where Protocol ==

extension RoutableServiceModule where Protocol ==

@protocol ... <ZIKViewRoutable>

@protocol ... <ZIKViewModuleRoutable>

@protocol ... <ZIKServiceRoutable>

@protocol ... <ZIKServiceModuleRoutable>

You can also get all protocols by runtime methods.

If you are using swift, Xcode will auto list all routable protocol:

Xcode Auto Completion

There're compile-time check when routing with protocols, so you won't use any undeclared protocols.

How to use the destination after performing route?

The router only keep week reference to the destination after performing route. You need to hold the destination if you want to use it later.

class TestViewController: UIViewController {
	var mySubview: MySubviewInput?
	
	func addMySubview() {
        Router.perform(
        to: RoutableView<MySubviewInput>(),
        path: .addAsSubview(from: self.view),
        configuring: { (config, _) in
            config.successHandler = { destination in
                self.mySubview = destination
            }
    	 })
	}
}
Objective-C Sample
@interface TestViewController: UIViewController
@property (nonatomic, strong) UIView<MySubviewInput> *mySubview;
@end
@implementation TestViewController

- (void)addMySubview {
    [ZIKRouterToView(MySubviewInput) performPath:ZIKViewRoutePath.addAsSubviewFrom(self.view) configuring:^(ZIKViewRouteConfiguration *config) {
        config.successHandler = ^(id<MySubviewInput> destination) {
            self.mySubview = destination;
        };
    }];
}

@end

What's the different betweenZIKViewRoutableandZIKViewModuleRoutable?

The same is betweenZIKServiceRoutableandZIKServiceModuleRoutable.

Destination protocol

ZIKViewRoutableis the parent protocol of destination protocol. If your module is simple and all dependencies can be set on destination, you only need to use protocol conformed by destination.

Module protocol

ZIKViewModuleRoutableis the parent protocol of module protocol. It's for declaring parameters used by the module.

When you need a module protocol ?

When the destination class uses custom initializer to create instance. router needs to get required parameter from the caller.

Or when your module contains multi components, and you need to pass parameters to those components. And those parameters are not belong to destination. you need a module config protocol to store them in configuration, and configure components' dependencies inside the router.

For example, when you pass a model to a VIPER module, the destination is the view in VIPER, and the view is not responsible for accepting any models.

You can see sample code in: Transfer Parameters with Custom Configuration.

What's required protocol and provided protocol?

required protocol is the protocol used by the module's user. provided protocol is the real protocol provided by the module. One provided protocol can has multi required protocol.

Why separating required protocol and provided protocol?

  • Module and module's user are isolated in code. Separating their protocols can decouple them thoroughly
  • The provided module can be replaced with any other module that can be adapted with the required protocol. The modules' manager (app context) is responsible for adapting required protocol and provided protocol
  • A module can declare its required protocols to explicitly declare its dependencies. Then it's much easier to provide mocked dependencies in unit test, without importing any third-party modules

Can required protocol and provided protocol provide different interface?

Methods in required protocol and provided protocol can be different, as long as they provide same function. You can adapt required protocol and provided protocol with category, extension, proxy and subclass. You can see sample code in: Module Adapter.

In most case, the required protocol is same as the provided protocol, but just change a name. You don't have to always separate required protocol and provided protocol. It's OK to use the same protocol in module and its user. Or you can just make a copy and change the protocol name, letting required protocol to be subset of provided protocol. You only need to do adapting when changing to another provided module.

But adapting with category, extension, proxy and subclass will write much more code, you should not abuse the adapting.

If functional module depends on each other, it's recomended to directly use the class, or expose dependencies in it's interface, letting the user to inject them.

Only do adapting when your module really allow multi modules to provide the required protocol. Such as login view module allows different service module in different app.

What's adapter?

ZIKViewRouteAdapter and ZIKServiceRouteAdapter are just for registering required protocol for other router. You still need to add required protocol for the provided module.

Where to put code for adapters?

Adapters exist in app context. Modules don't know those adapters. You can put them in a same adapter file, or in different adapter classes.

What's the different between ZRouter and ZIKRouter?

ZRouter encapsulates ZIKRouter, provides swifty methods for swift, and supports swift class and swift protocol.

Does ZIKRouter support swift value type?

NO. ZIKRouter only supports class type. Value type should not be used in different modules. If you really want to manage value types, you can provide value types with a value type factory protocol.

How to declare protocol with class at same time?

In swift, you can declare composed protocol:

typealias ViewControllerInput = UIViewController & ControllerInput

extension RoutableView where Protocol == ViewControllerInput {
    init() { self.init(declaredProtocol: Protocol.self) }
}

When fetching router with ViewControllerInput, you can get a UIViewController conforming to ControllerInput.

But we can't declare this in Objective-C.

How to handle route error?

In general, route errors appear in development stage. Errors are caused by:

  • Errors from UIKit when showing view controller, such as pushing a view controller when there is no navigationController
  • Pass wrong parameters or miss parameters when routing, so the router make this routing failed

You should solve route errors in development stage. You can track all errors in globalErrorHandler.

How to handle non-existent routing?

You may use non-existent url in URL router, and you can provide a default error view controller in this situation.

But with ZIKRouter, you won't use wrong protocol when routing. You only need to check whether the router exists when fetching router with identifier or URL. If the router is nil, you can use a default router to perform this route.