2

ユーザーがアクセサリをクリックする UITableView があります。アクセサリは、モーダル ビューで UIView を起動します ( を使用presentViewController)。

返されるとき、必要なデータでテーブルビュー セルを更新することを意味します。

現在、シングルトンを使用して辞書内の userData をキャプチャしています。しかし、NSNotification を使用しても同じ問題があります。

私の問題は、モーダル ダイアログを閉じると、テーブルビューが更新されないことです。ただし、スクロールするか物理的に移動すると、セルのエントリが更新されます。

セルまたはテーブルビュー全体を NSNotifications で強制的にリロードしようとすると、同じ結果が得られます。

これについて何か助けが得られるかどうか疑問に思っています。セルをリロードするにはどうすればよいですか?

セルの表示とモーダルの表示方法に関連するコードを以下に示します。

ノート;

_eventName is just a NSString

-(void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    if ( [[MySingleton sharedInstance].userData objectForKey:@"eventName"] !=nil) {
        _eventName = [[MySingleton sharedInstance].userData objectForKey:@"eventName"];
    }
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    NSDictionary *dict;
    NSString *name;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }

    dict = [_template objectAtIndex:indexPath.row];
    name = [dict objectForKey:@"name"];

    cell.textLabel.text = name;

    NSString *key = [[dict objectForKey:@"key"] lowercaseString];

    if ([[key lowercaseString] isEqualToString:@"name"]==YES) {
        cell.detailTextLabel.text = _eventName;
    }



    return cell;
}



-(void) tableView:(UITableView *)tv accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *dict = [_template objectAtIndex:indexPath.row];
    NSString *key = [[dict objectForKey:@"key"] lowercaseString];

    NSString *name = @"";

    if ([key isEqualToString:@"name"]==YES) {

        EventNameVC *nameEditor = [[EventNameVC alloc] initWithNibName:@"EventNameVC" bundle:nil];

        if (_eventName !=nil) {
            nameEditor.txtName.text = _eventName;
        } else {
            nameEditor.txtName.text = name;
        }

        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nameEditor];


// When we return from the view, reload the cell.
        [self presentViewController:nav animated:YES completion:^{

            [self.tv reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];

        }];

        nav = nil;
    }

}

編集:モーダルの閉鎖を検出するために通知を使用しようとしました。しかし、私はまだ同じ問題を抱えています。つまり、UITableView は、テーブルを物理的に移動したときに更新されたデータのみを表示します。

私のView Controllerではこれを行います。

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization

        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

        self.notificationObserver = [[NSNotificationCenter defaultCenter]
                                     addObserverForName:@"dismissModalView"
                                     object:nil
                                     queue:mainQueue
                                     usingBlock:^(NSNotification *notification) {
                                        NSLog(@"Notification received!");

                                        NSDictionary *userInfo = notification.userInfo;
                                        _eventName = [userInfo objectForKey:@"eventName"];

                                        NSLog(@"received._eventName = %@", _eventName);

                                         [self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:YES];
                                    }];

    }
    return self;
}

-(void) updateTable {
NSLog(@"%s", __PRETTY_FUNCTION__);
[self.tv reloadData];
}

accessoryButtonTappedForRowWithIndexPathメソッド内で modalView を起動します

EventNameVC *nameEditor = [[EventNameVC alloc] initWithNibName:@"EventNameVC" bundle:nil];
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nameEditor];
        [self presentViewController:nav animated:YES completion:nil];

さて、and を使用してモーダル ビューを起動するpresentViewControllerと、通知が発生します。

私のモーダルビューでは

-(IBAction) btnSave:(id)sender {
    [self.txtName resignFirstResponder];

    ///[[MySingleton sharedInstance].userData setObject:self.txtName.text forKey:@"eventName"];
    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:self.txtName.text forKey:@"eventName"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" object:self userInfo:userInfo];
    [self dismissViewControllerAnimated:YES completion:nil];
}

これを実行すると、updateTable が正しく起動され、コンソールに記録されます。

ここまでは順調ですね。

ただし、テーブルビューはまだデータを更新していません。セルを更新するには、テーブルを物理的に移動する必要があります。

セルを強制的に正しく更新するにはどうすればよいですか?

4

2 に答える 2

0

– reloadRowsAtIndexPaths:withRowAnimation:問題は、View Controller (nav) を提示するときに呼び出していることです。「完了」ブロックは、OSがView Controllerの表示を終了したときに実行され(ビューが戻ったときではなく)、ユーザーに表示されます。

– reloadRowsAtIndexPaths:withRowAnimation:ビューコントローラーを閉じるときに呼び出してみてください。それはの「完了」ブロックに入る可能性があります– dismissViewControllerAnimated:completion:

お役に立てれば!

アップデート:

こんにちはカーディガン; 私はあなたの更新された質問を見て、コントローラーupdateTableの却下後にメソッドが正しく呼び出されている場合、問題が別の場所にあることを意味します。EventNameVCテーブル ビューを呼び出すreloadDataと、データ ソースが を呼び出すまでに更新されていない場合を除き、基になるデータ ソースに加えた変更で内容が更新されますreloadData

メソッドを見る– tableView:cellForRowAtIndexPath:と、次の 2 行のコードからセルの情報を取得できることがわかります。

dict = [_template objectAtIndex:indexPath.row];
name = [dict objectForKey:@"name"];

情報は_template配列から取得されます。さて、あなたのモーダル ビューには、textName最終的にテーブル ビューに表示したいものだと私が想定しているプロパティがありますよね? _templateビューコントローラーが閉じられると、通知を使用してその情報を辞書内に送信しますが、その通知を受信すると、その情報を配列に追加するブロックのどこにも表示されません。データ ソースをどのように更新しますか?

以下もお試しください。

メソッドにブレークポイントを追加しますupdateTable。アプリケーションがそこで停止すると、別のブレークポイントが追加されますが、今回は– tableView:cellForRowAtIndexPath:メソッドに追加されます。reloadDataメソッドが正しく機能しているかどうかが表示されます。その後、アプリケーションが停止する場合– tableView:cellForRowAtIndexPath:は、正しい道を進んでいます。その時点で、データ ソースの内容の表示に進みます。これを行うpo _templateには、XCode コンソールに直接入力 (Enter キーを押します) します。そうすれば、必要な情報で更新されているかどうかを確認できます。

それがどうなるか教えてください。

于 2013-09-09T21:32:08.880 に答える
0

@LuisCeinの回答を受け入れました。テーブルビューを書き直しました。現在更新中です。

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization        
        self.pTemplate = [[MySingleton sharedInstance] pTemplate];

        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

        [[NSNotificationCenter defaultCenter]
         addObserverForName:@"dismissModalView"
         object:nil
         queue:mainQueue
         usingBlock:^(NSNotification *notification) {
             NSLog(@"Notification received!");

             NSDictionary *userInfo = notification.userInfo;
             _eventName = [userInfo objectForKey:@"eventName"];

             NSLog(@"received._eventName = %@", _eventName);

             [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
         }];

    }
    return self;
}

...

- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section
{
    return pTemplate.count;
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }

    NSDictionary *dict = [self.pTemplate objectAtIndex:indexPath.row];
    NSString *name = [dict objectForKey:@"name"];

    cell.textLabel.text = name;
    cell.detailTextLabel.text = @"Detail text";

    NSString *key = [[dict objectForKey:@"key"] lowercaseString];

    if ([[key lowercaseString] isEqualToString:@"name"]==YES) {

        if (_eventName !=nil) cell.detailTextLabel.text = _eventName;
    }

    if ([[key lowercaseString] isEqualToString:@"date"]==YES) {
        NSString *dateString = [dateFormater stringFromDate:_eventDate];
        if (_eventDate !=nil) cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", dateString];
    }

    if ([[key lowercaseString] isEqualToString:@"venue"]==YES) {
        if (_venueName != nil) cell.detailTextLabel.text = _venueName;
    }

    cell.detailTextLabel.textColor  = [UIColor darkGrayColor];

    return cell;
}

-(void) tableView:(UITableView *)tv accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *dict = [self.pTemplate objectAtIndex:indexPath.row];
    NSString *key = [[dict objectForKey:@"key"] lowercaseString];

    if ([key isEqualToString:@"name"]==YES) {

        if (_eventName !=nil) {
            [[MySingleton sharedInstance].userData setObject:_eventName forKey:@"eventName"];
        }

        EventNameVC *nameEditor = [[EventNameVC alloc] initWithNibName:@"EventNameVC" bundle:nil];

        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nameEditor];
        [self presentViewController:nav animated:YES completion:nil];

        nav = nil;
    }

    if ([key isEqualToString:@"date"]==YES) {

    }

    if ([key isEqualToString:@"venue"]==YES) {

    }
}

このコードは uitableview とセルを正しく表示しています。ビューに移動し、テキストを変更して、nsnotification を送信します。

-(IBAction) btnSave:(id)sender {
    [self.txtName resignFirstResponder];

    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:self.txtName.text forKey:@"eventName"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" object:self userInfo:userInfo];

    [self dismissViewControllerAnimated:YES completion:nil];
}

すべてが機能するようになりました。何もスクロールしなくても、uitableview が更新されるようになりました。

ばかげた間違いかもしれませんが、解決されてうれしいです。

助けてくれてありがとう!

于 2013-09-11T05:29:01.070 に答える