处理来自应用的非 Ui 部分的导航?

2022-09-02 22:35:08

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

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

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

请考虑以下事项。初始视图控制器已加载。用户点击了一个按钮。以下是两种可能的情况:

  1. 前端接收手势并打开请求的视图控制器

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

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

  • 起始页 : 主页面:UIViewControllerUINavigationViewController
  • > 主选项卡页 1:UIPageViewController
  • > 主选项卡第 2 页:UIPageViewController
  • > 主选项卡页 3: 设置:UIPageViewControllerUIViewController

如果您在应用程序的“到”级别上导航,则很简单。您只需告诉前端打开“起始页”,“主”或“设置”。但是,点击一个按钮从起始页或从主>主选项卡1转到主>主选项卡页3有什么用。您必须执行以下操作:

  • 如果你在Startpage上:你必须告诉前端它应该审查Main,然后是Main TabPage3。
  • 如果你在Main-TabPage1上>:你必须告诉前端它应该只显示Main-TabPage3。

你可以看到,对于这样一个简单的页面方案,在Java后端显示ViewController的事件似乎有很多情况需要考虑。

这是从Java后端揭示视图的有效方法,还是您认为有更好的方法?


答案 1

一个好的做法是将应用程序拆分为两部分:

:包含用于远程通信的所有服务类(即,如果需要命中远程后端),以及与业务逻辑相关的每个类和模型。此部分是使用 j2objc 的部分,您希望它未连接到您的 UI。

UI:所有视图控制器和视图都属于此处。

为什么它们彼此不同?

一旦你设置了所有的业务逻辑,你应该用j2objc生成你的代码,并且几乎不受影响。另一方面,您的UI可能会在应用程序的生命周期中发生很大变化(请记住iOS 7如何迫使每个开发人员刷新其应用程序的视觉效果)。您希望防止UI 中的更新影响其他部分。

它们如何协同工作?

在操作(即点击按钮)之后,您可以询问域是否满足某些先决条件(即它是否是新用户?),然后实例化ViewController以进行显示。UI 可能会向提供数据或要求一些数据,但它负责实例化视图/视图控制器。

复杂路由

在我需要能够根据远程推送通知或基于某些复杂逻辑导航到某个位置的应用程序中,我倾向于让对象(称为“路由器”)处理所有这些。它仍然驻留在 UI 部分中,并且你向它传递做出决策所需的域对象。然后,它返回一个导航对象,该对象描述导航堆栈(它可能是处理类似于 URL 的字符串的对象),您可以递归地将其提供给 viewControllers。

假设您的“路由器”对象将导航对象“firstVC/secondVC/threeVC”返回到 AppDelegate。AppDelegate可以调用返回“firstVC”的方法,并基于此实例化“firstViewController”对象以添加到UINavigationController的堆栈中。然后,它将“路由器”对象传递给这个新实例化的ViewController,后者也调用该方法来接收“secondVC”。基于此,“firstViewController”将实例化“secondViewController”对象以添加到UINavigationController的堆栈中。然后,它将相同的“路由器”对象传递给该“secondViewController”对象,并且该对象将再次调用该方法来获取“thirdVC”并实例化相应的ViewController。dequeuedequeuedequeue

这样,您就可以通过让每个 ViewController 实例化它所知道的另一个 ViewController 来构建导航堆栈(在我前面的示例中,“firstViewController”知道“secondViewController”,因为它的视图有一个按钮,允许用户访问“secondViewController”的视图,但不知道“thirdViewController”)。

您也可以让 AppDelegate 构建整个导航堆栈,但由于您的“firstViewController”已经导入了“secondViewController”标头以使按钮正常工作,因此最好让他执行与该 ViewController 关联的工作,依此类推。

工作样本

这是一个演示项目我做了一个说明我刚刚暴露的东西。

“域”文件夹中包含的类可能是使用 j2objc 生成的类。AppDelegate 中的方法使用“路由器”对象生成功能导航堆栈。我使这个项目框架变得简单,同时展示了一些模式,比如用于集中和有组织的类实例化的工厂,以及封装模型对象和输出数据准备显示的 viewData。它可以通过一些协议进行改进,以使事情更加抽象,但是为了演示,我试图保持简单。buildNavigationStack


答案 2

我认为一个好方法是从应用程序后端发送本地通知,让视图响应它并显示正确的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];
    }
}

推荐