18

注意:当我谈论应用后端时,我并不是指服务器后端。应用程序后端是应用程序的一部分。它是应用程序的非 ui 部分。

我有一个代码设计问题。使用 j2objc Java 被用作 iOS 应用程序的后端,其中前端仍然是 Objective-C。

哪个部分(前端或后端)应控制此模型中的导航?

考虑以下。初始 ViewController 已加载。用户点击了一个按钮。以下是两种可能的情况:

  1. 前端接收到手势并打开请求的 ViewController

  2. 前端接收手势并将动作报告给 Java 后端。Java 后端决定接下来要打开哪个页面,并告诉前端要显示哪个 ViewController。

对我来说,第二种解决方案似乎在代码分离方面更有意义。但是有一个问题发生在我身上。假设您的应用中有以下 ViewController 结构:

  • 起始页:UIViewController主要: UINavigationViewController
  • > Main-TabPage1:UIPageViewController
  • > Main-TabPage2:UIPageViewController
  • > Main-TabPage3:UIPageViewController设置: UIViewController

如果您在应用程序的“到”级别导航,这很简单。您只需告诉前端打开 Startpage、Main 或 Settings。但是,点击一个按钮从 Startpage 或 Main > Main-TabPage1 转到 Main > Main-TabPage3 有什么用。您必须执行以下操作:

  • 如果您在起始页上:您必须告诉前端它应该查看 Main,然后是 Main TabPage3。
  • 如果您在 Main > Main-TabPage1:您必须告诉前端它应该只显示 Main-TabPage3。

您会看到这样一个简单的页面方案显示 Java 后端的 ViewController 的事件似乎有很多情况需要考虑。

这是从 Java 后端显示视图的有效方式,还是您看到更好的方式?

4

2 回答 2

4

A good practice is indeed to split your application in two parts:

The domain: Contains all the service classes for remote communications (that is, if you need to hit a distant backend), and every classes and models related to your business logic. This part is the one that use j2objc, and you want it to be unconnected to your UI.

The UI: All the ViewControllers and Views belongs here.

Why are they distinct from each other?

Once you are set with all your business logic, you should be good to generate your code with j2objc and leave it practically untouched. Your UI, on the other end, may change a lot in the lifespan of your application (remember how iOS 7 forced every developer to refresh the visual of their applications). You want to keep updates in the domain or the UI from impacting the other part.

How do they work together?

Following an action (i.e. a tap on a button), you may ask the domain if some prerequisites are met (i.e is it a new user?), and then you instantiate a ViewController for display. The UI may give data to the domain or ask for some, but it is its responsibility to instantiate Views/ViewControllers.

Complex routing

In applications where I need to be able to navigate somewhere based on a remote push notification, or based on some complex logic, I tend to let an object (called a "router") handle all of this. It still reside in the UI part, and you pass it the domain objects required to make the decisions. It then returns a navigation object depicting a navigation stack (it could be an object handling a string similar to an URL) that you could give recursively to you viewControllers.

Let say your "router" object returns a navigation object "firstVC/secondVC/thirdVC" to the AppDelegate. The AppDelegate could call a dequeue method that returns "firstVC", and based on this instantiate a "firstViewController" object to add in a UINavigationController's stack. It then pass the "router" object to this newly instantiated ViewController, who also call the dequeue method to receive "secondVC". Based on this, "firstViewController" would instantiate a "secondViewController" object to add to the UINavigationController's stack. It would then pass the same "router" object to that "secondViewController" object, and that one would again call the dequeue method to get "thirdVC" and instantiate the appropriate ViewController.

That way, you build your navigation stack by letting every ViewController instantiate another ViewController it knows about (in my previous example, "firstViewController" knows about "secondViewController" because its view has a button allowing the user to reach "secondViewController"'s view, but doesn't know about "thirdViewController").

You could also have your AppDelegate build the whole navigation stack, but since your "firstViewController" already have "secondViewController" header imported for the button to work, it is better to let him do the job associated with that ViewController, etc.

Working sample

Here is a demo project I made to illustrate what I just exposed.

Classes contained in the "Domain" folder could be your classes generated with j2objc. The buildNavigationStack method in AppDelegate build a functional navigation stack with a 'Router' object. I made this project skeleton simple while showcasing a few patterns, like the factories for a centralized & organized class instantiations, and the viewData that encapsulate a model object and output data ready for display. It could be improved with a few protocols to make things a little more abstract, but I tried to keep it simple since the for the sake of the presentation.

于 2015-04-21T03:37:29.427 回答
1

我认为一个好方法是从 App Backend 发送本地通知并让视图响应它并显示正确的 ViewController 并进行调整,如果视图不可见,它应该执行视图中的操作

例如,在您解释的情况下,代码将如下所示:

从后端:

NSDictionary *userInfo = @{@"view": @"TabPage3"};
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:@"ShowView" object:nil userInfo:userInfo];`

在主视图里面

- (void)viewDidLoad {
    [self viewDidLoad];
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self selector:@selector(showView:) name:@"ShowView" object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    if(self.receivedNotification != nil){
        [self showView:self.receivedNotification];
        self.receivedNotification = nil;
    }
}
- (void)showView:(NSNotification*)notification {
    if (viewController.isViewLoaded && viewController.view.window) {
        // viewController is visible
        if ([notification.userInfo valueForKey:@"TabPage3"]){
            [self.tabBarController setSelectedIndex:3];
        }
    } else {
        self.receivedNotification = notification;
    }
}

在起始页内

- (void)viewDidLoad {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self selector:@selector(showView:) name:@"ShowView" object:nil];
}
- (void)showView:(NSNotification*)notification {
    if ([notification.userInfo valueForKey:@"TabPage3"]){
        [self.NavigationController pushViewController:mainViewController animated:YES];
    }
}
于 2015-04-24T16:43:30.707 回答