18

私は xcode を初めて使用します。基本的に、多くのレベルを持つ埋め込みテーブルビューであるサンプル アプリを開発しようとしています。各テーブルビューのセルを格納する plist があります。セルに子がない場合は、セルを押すと 1 つの詳細ビューに移動できるようにしたいと考えています。最終的には、データ型に応じてさまざまな詳細ビューに移動できるようにしたいと考えています。これを行うには、ストーリーボードから詳細ビューを作成し、View Controller を詳細ビューにドラッグして手動の「プッシュ」セグエを作成し、セグエに「segue1」というラベルを付けました。

編集:ソースコードはこちら

ビルド マニュアル セグエ

次に、これが機能するために必要な関数と思われるものを入力します。これ[self performSegueWithIdentifier:@"segue1" sender:myString];は、選択したセルのタイトルである myString を呼び出すことです。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //Check the dictionary to see what cell was clicked
    NSDictionary *dict = [self.tableDataSource objectAtIndex:indexPath.row];
    NSString *myString = [dict objectForKey:@"Title"];
    NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row];

    NSArray *children = [dictionary objectForKey:@"Children"];

    //If there is no children, go to the detailed view
    if([children count] == 0)
    {
        [self performSegueWithIdentifier:@"segue1" sender:myString];

    }
    else{
        //Prepare to tableview.
        DrillDownViewController *rvController = [[DrillDownViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];

        //Increment the Current View
        rvController.CurrentLevel += 1;

        //Set the title;
        rvController.CurrentTitle = [dictionary objectForKey:@"Title"];

        //Push the new table view on the stack
        [self.navigationController pushViewController:rvController animated:YES];

        rvController.tableDataSource = children;

    }

}

最後に、segue1 というラベルの付いたセグエを探す、segue の準備を呼び出しました。

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"segue1"])
    {
        DrillDownDetailController *dvController = [[segue destinationViewController] visibleViewController];
        //DrillDownDetailController *dvController = [[DrillDownDetailController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];
        [dvController setItemName:(NSString *)sender];
        [self.navigationController pushViewController:dvController animated:YES];
    }
}

これで動くと思っていたのですが、なぜかコードが に到達するたびに[self performSegueWithIdentifier:@"segue1" sender:myString];エラーで壊れてしまいます

***** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver () has no segue with identifier 'segue1'' * First throw call stack: (0x14b4022 0xeb4cd6 0xdf61b 0x3590 0xa85c5 0xa87fa 0x93d85d 0x1488936 0x14883d7 0x13eb790 0x13ead84 0x13eac9b 0x139d7d8 0x139d88a 0x17626 0x23ed 0x2355 0x1) 例外をスローして終了します (lldb)

ストーリーボードとコードで既に定義されているのに、なぜ segue1 が見つからないと言っているのかわかりません。

4

2 に答える 2

23

実際には、いくつかの問題があります。

まず、あなたがアップロードしたプロジェクトでは、セグエに「segue1」識別子がありません。

識別子なし

まだ識別子を入力していない場合は、入力する必要があります。

次に、テーブル ビューからテーブル ビューにプッシュするときにinitWithNibName、ビュー コントローラーを作成するために呼び出しています。あなたは本当に使いたいですinstantiateViewControllerWithIdentifier

したがって、次の行は次のようになります。

DrillDownViewController *rvController = [[DrillDownViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];

言うべきです:

DrillDownViewController *rvController = [self.storyboard instantiateViewControllerWithIdentifier:@"TableView"];

第三に、あなたprepareForSegueは:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"segue1"])
    {
        dvController = [[segue destinationViewController] visibleViewController];
        [dvController setItemName:self->nameToSend];
    }
}

また、への参照を排除するために単純化する必要がありますvisibleViewController。たとえば、次のようになります。

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"segue1"])
    {
        dvController = segue.destinationViewController;
        dvController.itemName = nameToSend;
    }
}

4 番目に、次のDrillDownDetailController.mメソッドがあります。

-(void) setItemName:(NSString *)itemName
{
    if(!itemName)
    {
        itemName = [[NSString alloc] initWithString:itemName];
    }
    label.text = itemName;
}

ここにはたくさんの問題がありますが、ここを更新するべきlabel.textではありません (まだ作成されていない可能性があるためです!)。このカスタム セッター メソッドを完全に削除し (Xcode に標準セッターを合成させるだけです)、viewDidLoad次のように変更する必要があります。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    label.text = self.itemName;
}

まで UI オブジェクトを更新しないでくださいviewDidLoad

プログラム全体を確認したわけではありませんが、これら 4 つの修正を行った後、「SubItem1」、「Cars」、「BMW」の順にタップすると、「BMW」という詳細画面が表示されます。他のアイテムの plist にはいくつかの問題があると思います (たとえば、靴のエントリは文字列であり、辞書のエントリではなく、エラーが発生します... plist に完全に入力していないだけだと思います)、上記の修正より重要なコーディングの問題を修正します。

于 2012-09-20T21:05:49.007 に答える
2

主な問題はここにあります。ストーリーボードからのものを再利用するのではなく、空のDrillDownViewControllerを作成していました。以下のコードのコメントを参照してください

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        if([[segue identifier] isEqualToString:@"segue1"])
        {
             [segue.destinationViewController setItemName:(NSString*)sender];
        }
    }

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //Check the dictionary to see what cell was clicked
       NSDictionary *dict = [self.tableDataSource objectAtIndex:indexPath.row];
NSString *titleName = [dict objectForKey:@"Title"];
NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row];

NSArray *children = [dictionary objectForKey:@"Children"];

if([children count] == 0)
{
    [self performSegueWithIdentifier:@"segue1" sender:titleName];

}
        else{
    //Prepare to tableview.

    //THE MAIN ISSUE IS HERE, you were creating a blank DrillDownViewController, not reusing the one from storyboards so it did not have a segue at all defined. instead do this:
    UIStoryboard*  sb = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                  bundle:nil];
    DrillDownViewController *rvController = [sb instantiateViewControllerWithIdentifier:@"DDVC"];       
    //Increment the Current View
    rvController.CurrentLevel += 1;

    //Set the title;
    rvController.CurrentTitle = [dictionary objectForKey:@"Title"];

    //Push the new table view on the stack
    [self.navigationController pushViewController:rvController animated:YES];

    rvController.tableDataSource = children;

}


    }
于 2012-09-20T18:41:50.713 に答える