18

注:アプリ バックエンドについて話すとき、サーバー バックエンドを意味するわけではありません。アプリ バックエンドはアプリの一部です。アプリの非 UI 部分です。

コード設計について質問があります。j2objc の使用 Java は iOS アプリのバックエンドとして使用されますが、フロントエンドはまだ Objective-C です。

このモデルでナビゲーションを制御するのはどの部分 (フロントエンドまたはバックエンド) ですか?

以下を検討してください。最初の ViewController がロードされました。ユーザーがボタンをタップしました。次の 2 つのケースが考えられます。

  1. フロントエンドがジェスチャを受け取り、要求された ViewController を開きます

  2. フロントエンドはジェスチャを受け取り、そのアクションを Java バックエンドに報告します。Java バックエンドは、次に開くページを決定し、どの ViewController を表示するかをフロントエンドに伝えます。

私には、2 番目の解決策は、コード分離の順番でより理にかなっているように思えます。しかし、私に発生した1つの問題があります。アプリに次の ViewController 構造があるとします。

  • 開始ページ:UIViewControllerメイン: UINavigationViewController
  • > メイン-TabPage1:UIPageViewController
  • > メイン-TabPage2:UIPageViewController
  • > Main-TabPage3:UIPageViewController設定: UIViewController

アプリの to レベルをナビゲートする場合は簡単です。フロントエンドにスタートページ、メイン、または設定を開くように指示するだけです。しかし、ボタンをタップして Startpage または Main > Main-TabPage1 から Main > Main-TabPage3 に移動するのは何の役に立つでしょう。次のことを行う必要があります。

  • Startpage を使用している場合: フロント エンドに、Main を確認してから Main TabPage3 を確認するように指示する必要があります。
  • Main > Main-TabPage1 を使用している場合: Main-TabPage3 のみを表示するようにフロント エンドに指示する必要があります。

Java バックエンドから ViewController を明らかにするこのような単純なページ スキームのイベントには、考慮すべき多くのケースがあるようです。

これは、Java バックエンドからビューを公開する有効な方法ですか、それとももっと良い方法はありますか?

4

2 に答える 2

4

アプリケーションを 2 つの部分に分割することをお勧めします。

ドメイン:リモート通信用のすべてのサービス クラス(つまり、離れたバックエンドにアクセスする必要がある場合) と、ビジネス ロジックに関連するすべてのクラスとモデルが含まれています。この部分は j2objc を使用する部分であり、UI に接続しないようにする必要があります。

UI : すべての ViewControllers と Views がここに属します。

なぜそれらは互いに異なっているのですか?

すべてのビジネス ロジックを設定したら、j2objc を使用してコードを生成し、実質的にそのままにしておくことができます。一方、UI は、アプリケーションの存続期間中に大きく変化する可能性があります (iOS 7 では、すべての開発者がアプリケーションのビジュアルを更新することを余儀なくされたことを思い出してください)。ドメインまたはUIの更新が他の部分に影響を与えないようにする必要があります。

それらはどのように連携しますか?

アクション (つまり、ボタンのタップ) に続いて、いくつかの前提条件が満たされているかどうか (つまり、新しいユーザーかどうか) をドメインに尋ねてから、ViewController をインスタンス化して表示します。UIはドメインにデータを提供したり要求したりすることがありますが、Views/ViewControllers をインスタンス化するのはUIの役割です。

複雑なルーティング

リモート プッシュ通知に基づいて、または複雑なロジックに基づいてどこかにナビゲートできるようにする必要があるアプリケーションでは、オブジェクト (「ルーター」と呼ばれます) にこれらすべてを処理させる傾向があります。これは引き続き UI 部分に存在し、決定を下すために必要なドメイン オブジェクトを渡します。次に、viewController に再帰的に与えることができるナビゲーション スタック (URL に似た文字列を処理するオブジェクトである可能性があります) を表すナビゲーション オブジェクトを返します。

「ルーター」オブジェクトがナビゲーション オブジェクト「firstVC/secondVC/thirdVC」を AppDelegate に返すとします。AppDelegate は「firstVC」を返すメソッドを呼び出し、dequeueこれに基づいて「firstViewController」オブジェクトをインスタンス化して UINavigationController のスタックに追加することができます。次に、この新しくインスタンス化された ViewController に「router」オブジェクトを渡します。ViewController は、dequeueメソッドを呼び出して「secondVC」を受け取ります。これに基づいて、「firstViewController」は「secondViewController」オブジェクトをインスタンス化し、UINavigationController のスタックに追加します。dequeue次に、同じ「router」オブジェクトをその「secondViewController」オブジェクトに渡し、そのメソッドを再度呼び出して「thirdVC」を取得します。

このようにして、すべての ViewController が認識している別の ViewController をインスタンス化できるようにすることで、ナビゲーション スタックを構築します (前の例では、「firstViewController」は「secondViewController」を認識しています。そのビューには、ユーザーが「secondViewController」のビューにアクセスできるボタンがあるためです。しかし、「secondViewController」については知りません)。

AppDelegate にナビゲーション スタック全体を構築させることもできますが、「firstViewController」にはボタンが機能するようにインポートされた「secondViewController」ヘッダーが既にあるため、その ViewController に関連付けられたジョブを彼に任せた方がよいでしょう。

作業サンプル

これは、私が公開した内容を説明するために作成したデモ プロジェクトです。

「Domain」フォルダに含まれるクラスは、j2objc で生成されたクラスである可能性があります。buildNavigationStackAppDelegateのメソッドは、「Router」オブジェクトを使用して機能的なナビゲーション スタックを構築します。このプロジェクトの骨組みをシンプルにしながら、集中化および組織化されたクラスのインスタンス化のためのファクトリや、モデル オブジェクトをカプセル化し、表示可能な出力データを出力する viewData などのいくつかのパターンを紹介しました。物事をもう少し抽象化するためにいくつかのプロトコルを使用して改善することができますが、プレゼンテーションのために単純に保つように努めました.

于 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 に答える