0

私は iOS プログラミングが初めてなので、全体がどのように機能するかを理解できるように、このことをゼロから作成したいと考えています。そのため、マスター詳細テンプレートを使用する代わりに、これをゼロから行いました。

マスター ビューと詳細ビューの間でデータを渡すという点で、大きな障害があります。現時点では、マスター ビューの項目をタップすると、詳細ビ​​ュー コントローラーの最初のビューが検索されます。これを と呼びましょうmainswitchviewcontrollerViewControllerセグエ経由で詳細コントローラー部分に接続するのは最初UINavigationControllerです(下の画像を参照してください)。

これはログイン後に発生しviewcontroller、アプリ全体にアクセスする前にユーザーにオプションを選択してもらいます。ViewControllerこれにより、フローの最後に進みます(下の画像 - 赤い丸を参照)。

フロー図

今私がやろうとしていることはこれです:

@interface MasterListViewController : UITableViewController{
}

@property (nonatomic) int matNum;
@property (strong, nonatomic) DetailStaffMainContentViewController *detailViewController;
@end

:
:

@implementation MasterListViewController
@synthesize matNum;
:
:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    for(UIViewController *vc in self.splitViewController.viewControllers){
        NSLog(@"%@)", vc.title);
    }

    self.detailViewController.teststring = @"gronk";
}

これは私のdetailViewController(アクセスしたいもの)です

@implementation DetailStaffMainContentViewController
@synthesize tableView;
@synthesize teststring;
@synthesize lblOutput;

teststring行を選択したら、コントローラーにそのラベルを設定するために使用する を割り当てます。それが私がしたことです。

私の質問は次のとおりです。

  1. エラーが発生します。私が何を間違っていたのだろうか?

    [MainSwitchBoardViewController setTeststring:]: unrecognized selector
    sent to instance 0x7572190
    
  2. これはデータを渡すための推奨される方法ですか? それとも、通知センターに固執する必要がありますか?

考え?

編集 アプリの流れを説明するだけです:

  1. ユーザーがログインします (ユーザー名が存在しない場合、フローティング ビューコントローラーがポップアップし、ユーザーに強制的にログインさせます。

  2. ユーザーがログインすると、ポップアップが消えて、現在のセッションで使用するロールのタイプ (例: スタッフまたはファイター) をユーザーに尋ねます。

  3. ユーザーがファイターを選択した場合、ユーザーはトップ VC にプッシュされます。ユーザーがスタッフを選択した場合、ユーザーはボトム VC (コレクション コントローラー) にプッシュされます。

  4. FOR スタッフ: 現在、この [self perfermSegueWithIdentifier:sender:self] で最後の VC にプッシュしています。

    ユーザーに最後の VC (DetailsS​​taffView) が表示されたら、これをユーザーがトランザクションを実行するメインの詳細ビューにしたいと考えています。さらにいくつかのポップアップ?(または、特定のトランザクションのために別の VC への別のプッシュを追加する必要があるかもしれません)。しかし、最終的には、ユーザーが最初の Viewcontroller (MasterSwitchBoard)にアクセスすることを望まない

編集 2 これは、ログイン後の最初の VC を制御するメイン スイッチ ボード クラスです。

@interface MainSwitchBoardViewController : UIViewController{

}

@property (strong, nonatomic) IBOutlet UILabel *txtLabel;
- (IBAction)btnStaff:(id)sender;
- (IBAction)btnAdmin:(id)sender;

@end

これは、atm が最後の VC に自動的にプッシュするコレクション VC です。最初はこれで通知を使用していましたが、不要のようで削除しました。

@interface MatListCollectionViewController ()

@end

@implementation MatListCollectionViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self performSegueWithIdentifier:@"SeguePushToStaffDetailFromMats" sender:self];
}

そして詳細スタッフ

@interface DetailStaffMainContentViewController : UIViewController{

}

@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, retain) IBOutlet UILabel *lblOutput;
@property (nonatomic, retain) NSString *teststring;

@end


    @implementation DetailStaffMainContentViewController
    @synthesize tableView;
    @synthesize teststring;
    @synthesize lblOutput;
4

2 に答える 2

3

私は逆の順序でそれらに取り組みます:

これはデータを渡すための推奨される方法ですか? それとも、通知センターに固執する必要がありますか?

理論的には通知センターを使用できますが、この場合は使用しません。個人的には、次のNSNotificationCenter場合にのみ使用します。

  • ビューコントローラーの状態を知る合理的な方法がない非同期プロセスを実行しています(たとえば、サーバーからのデータの更新に時間がかかるバックグラウンドタスクがあり、ユーザーはサーバー内のほぼどこにでも移動できた可能性があります更新が完了したことをView Controllerに通知する準備が整うまでにアプリ); および/または

  • 何らかのイベントを通知したい複数のオブジェクトがある可能性があります。

ここでは、これらの条件はどちらも当てはまりません。確かに を使用できますNSNotificationCenterが、それは不要なはずです。通常は、プロパティを明示的に設定することをお勧めします。

エラーが発生します。私が何を間違っていたのだろうか?

残念ながら、これまでに提示した証拠に基づいて判断するのは困難です。しかし、あなたのコードとコメントに基づいて調整するのに苦労していることがいくつかあります。

  • であると宣言detailViewControllerしましたDetailStaffMainContentViewController(これは、アクセサーを合成したクラスですteststring);

  • detailViewControllerしかし、あなたのエラーメッセージは、それが明らかにオブジェクトであることを示唆してMainSwitchBoardViewControllerいます(アクセサメソッドを理解していませんsetTeststring); と

  • をどのように設定しているかを示していないdetailViewControllerため、ここでどこが間違っているかを言うのは困難です。

個人的には、このような場合、ビュー コントローラーへのポインターを維持するためのプロパティを定義することにはいつも消極的です。私は通常UISplitViewControllerdetail分割の内容を尋ねたいと思います。したがって、そのためのクラス プロパティ/ivar を用意するのではなく、マスター ビュー コントローラーに次のようなメソッドを用意します。

- (UIViewController *)detailViewController
{
    return [[self.splitViewController.viewControllers lastObject] topViewController];
}

これは基本的に、「分割ビュー コントローラーの (詳細分割) の配列から最後のオブジェクトを取得し、viewControllers(個人的には) その詳細分割で常にナビゲーション コントローラーを使用するため、 を使用して、その詳細にあるtopViewControllerサブクラスへのポインターを取得しましょう」と言っています。UIViewController分割 (ナビゲーション コントローラー内に埋め込まれています)。

次にdidSelectRowAtIndexPath、そのView Controllerが期待どおりのものであるかどうかを確認します。そうでない場合は、それに続きます(prepareSegue必要なデータをそのコントローラーに渡します)。

たとえば、次のストーリーボードを考えてみましょう。

サンプル絵コンテ

ここで、「A」はデフォルトの詳細コントローラーです。「B」は、「A」を置き換えたランダムなシーンかもしれません。「C」は実際の詳細ビュー コントローラーで、マスター ビュー コントローラーのテーブル ビューから選択したアイテムの詳細を確認できます。したがって、didSelectRowAtIndexPathマスター ビュー コントローラーの my は次のようになります。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIViewController *controller = [self detailViewController];

    if (![controller isKindOfClass:[DetailCViewController class]])
    {
        // if I'm not already showing "C" in my detail split, then let's segue to it

        [self performSegueWithIdentifier:@"GoToC" sender:self];
    }
    else
    {
        // if I'm already showing "C" in my detail split, let's just set the item of data I want to pass to it

        DetailCViewController *cController = (DetailCViewController *)controller;

        cController.detailItem = self.objects[indexPath.row];
    }

    // I have a method I call to make sure that the popover menu for the master view
    // controller disappears (in case it popped up since I was in portrait mode) and
    // adds the master view controller button to the navigation bar if I need it.

    [self removePopoverAndAddNavigationButton];
}

「C」にセグエする必要がある場合は、必要に応じて `prepareSegue に detailItem を渡します。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"GoToC"])
    {
        DetailCViewController *cController = (DetailCViewController *)[segue.destinationViewController topViewController];

        cController.detailItem = self.objects[[[self.tableView indexPathForSelectedRow] row]];
    }
}

私が言ったように、なぜあなたdetailViewControllerのオブジェクトのタイプが間違っているのかを理解しようとするのは難しいですが、これは私がこのようなことに取り組む方法です.

于 2013-02-19T05:24:59.050 に答える
2

ストーリーボードセグエについて説明している最後のWWDCの素敵な映画を最初に見てみるべきかもしれません。

あなたが提供したコードには、セグエについて書かれたものは何もありません。必ずIBを介して、またはプログラムでを介してセグエを使用してください[self performSegueWithIdentifier:]AppleDocsを参照してください

次に、youtViewControllerで追加の操作を提供できます。

  • [view shouldPerformSegueWithIdentifier:sender:]
  • [view prepareForSegue:sender:]

最初のものは、セグエを実行するかどうかを決定します。2つ目は、セグエが実行される直前に実行されます。secon操作内で、destinationViewControllerに情報を提供できます。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"showIssuesByProject"]){
        if (_searchActive) {
            ((IssueListViewController *)segue.destinationViewController).project = [_filteredProjects projectAtIndex:[self.tableView indexPathForSelectedRow].row];
        } else {
            ((IssueListViewController *)segue.destinationViewController).project = [_projects projectAtIndex:[self.tableView indexPathForSelectedRow].row];
        }
    }
    if ([segue.identifier isEqualToString:@"showIssuesByFilter"]) {
        ((IssueListViewController *)segue.destinationViewController).filter = [_filters filterAtIndex:[self.tableView indexPathForSelectedRow].row];
    }
}

注意:UISplitViewControll.viewControllersは、マスターコントローラーとディテールコントローラーの2つのコントローラーのみです。

于 2013-02-18T15:52:49.107 に答える