自定义UITableView单元格中的UILabel未随Core Data更改而更新

时间:2014-12-03 15:05:54

标签: ios objective-c uitableview core-data nsfetchedresultscontroller

我正在尝试构建一个游戏评分应用程序,该应用程序利用带有播放器照片,名称,按钮等的自定义表格单元格...在tableview的自定义单元格中直接添加/减去按钮,这些按钮正在点击我的保存方法,并将其存储在特定用户的Core Data中。

问题在于屏幕上的分数没有更新并反映出变化。在对Core Data的保存操作完成后,我正在调用 [self.tableView reloadData]; ......没有。但是,如果我重新启动应用程序,则会显示分数的变化(对于我点击过的任何玩家)。

也许我正在努力实现这一点,或者说,或者我只是没有抓住真正的问题。

思考/评论? 提前感谢您的负担。 : - )

很抱歉,如果这是过度杀伤,但这是我的实施文件的大部分内容:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self resetViews];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    [context setUndoManager:nil];
    _managedObjectContext = context;

    self.tableView.delegate = self;

    [self setNeedsStatusBarAppearanceUpdate];
}


-(void)resetViews {

    NSLog(@"\n\n\nresetViews()");

    [self setupFetchedResultsController];
    [self.tableView reloadData];
    [self.view setNeedsDisplay];
}

- (void)setupFetchedResultsController {

    NSString *entityName = @"Players";
    NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entityName);

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];

    request.sortDescriptors = [NSArray arrayWithObject:
                               [NSSortDescriptor
                                sortDescriptorWithKey:@"playerName"
                                ascending:YES
                                selector:@selector(localizedCaseInsensitiveCompare:)]];

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                        managedObjectContext:self.managedObjectContext
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];

    NSError *error;
    NSArray *results = [_managedObjectContext executeFetchRequest:request error:&error];
    _playerArray = [[NSMutableArray alloc]initWithArray:results];

    NSLog(@"_playerArray count: %i", [_playerArray count]);
    NSLog(@"\n");
}

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

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *cellIdentifier = @"playerCell";
    ScoringCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    // Configure the cell...
    Players *player_info = [_playerArray objectAtIndex:indexPath.row];

    NSSet *score = player_info.scores;

    for (Scoring *perObj in score){
        cell.lblPlayerScore.text = [perObj.score stringValue];
        NSLog(@"\n\n\n score for %@: %@", player_info.playerName, perObj.score);
    }

    cell.lblPlayerName.text = player_info.playerName;
    cell.lblPlayerNickName.text = player_info.playerNickName;
    cell.btnIncreaseScore.tag = indexPath.row;
    cell.btnDecreaseScore.tag = indexPath.row;
    cell.imgPlayerPhoto.image = [UIImage imageNamed:@"tmp_playerImage"];

    return cell;
}


- (IBAction)increaseScore:(id)sender {

    NSLog(@"PageContentViewController: increaseScore()");
    UIButton* btn=(UIButton*)sender;
    int selectedPlayerInt = btn.tag;
    //NSLog(@"Selected row is: %d",btn.tag);

    Players *player_info = [_playerArray objectAtIndex:selectedPlayerInt];
    [self updateRowScore:player_info:@"add"];
}

- (IBAction)decreaseScore:(id)sender {

    NSLog(@"PageContentView: decreaseScore()");
    UIButton* btn=(UIButton*)sender;
    int selectedPlayerInt = btn.tag;
    //NSLog(@"Selected row is: %d",btn.tag);

    Players *player_info = [_playerArray objectAtIndex:selectedPlayerInt];
    [self updateRowScore:player_info:@"subtract"];
}

-(void)updateRowScore: (Players *)player_info :(NSString *)modifier {

    NSLog(@"\n\nupdateRowScore()");
    NSLog(@"Update score (%@) for: %@\n", modifier, player_info.playerName);

    NSArray *scoreDataArray;

    if ([self playerScoreCount:player_info] == 0) {

        // NEW score... we've never scored before.
        Scoring *scoring_data = [NSEntityDescription
                                 insertNewObjectForEntityForName:@"Scoring"
                                 inManagedObjectContext:_managedObjectContext];

        //Since this is the first score, always set it to 1
        scoring_data.score = [NSNumber numberWithInt:1];
        scoring_data.holeNumber = [NSNumber numberWithInt:_pageIndex];
        scoring_data.scoredBy = player_info;

    } else {

        //Update existing player score..
        NSError *error = nil;
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

        NSEntityDescription *BEntity = [NSEntityDescription entityForName:@"Scoring" inManagedObjectContext:_managedObjectContext];
        [fetchRequest setEntity:BEntity];

        NSPredicate *predicate = [NSPredicate
                                  predicateWithFormat:@"(scoredBy = %@)", [player_info objectID]];
        [fetchRequest setPredicate:predicate];

        NSArray *results = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
        scoreDataArray = [[NSMutableArray alloc]initWithArray:results];

        Scoring *score_update = [scoreDataArray objectAtIndex:0];
        int currentScore = [score_update.score intValue];
        NSLog(@"current score: %d", currentScore);

        if ([modifier  isEqual: @"add"]) {
            currentScore++;
        } else {

            // Don't allow negative scores.
            if (currentScore >= 1) {
                currentScore--;
            } else {
                currentScore = 0;
            }
        }

        NSLog(@"NEW score: %d", currentScore);
        score_update.score = [NSNumber numberWithInt:currentScore];
    }


    // write to database
    [self.managedObjectContext save:nil];

    [self resetViews];
}

enter image description here


更新 感谢提示bbarnhart ......之前我已阅读过该帖子并将其用于我已经开始的基础。决定更进一步,使用更多Ray Wenderlich示例重构一大堆代码。

我已经看到了对录制内容的一些改进,并通过NSLog报告了......但是视图仍然没有改变。

操作正在增加分数,然后我使用[self configureCell:cell atIndexPath:path];重置单元格...在那里......负责向显示器发送文本的方法...... NSLog显示{{1当显示屏仍然只显示3时。

我知道这是一些愚蠢的新秀动作......我只是做了一些我无法弄清楚的错误。这是修改后代码的片段。

2014-12-04 22:40:40.199 appName[7153:150248] Score for Tim: 4

----------

更新 已经有一段时间了,因为我有机会重新访问,并且在启用提示后发现了一个新问题。当在列表中向下或向上滚动并超出正常边界时,tableview数据似乎会覆盖当前行上方或下方的行的显示。很奇怪......不确定这个动画Gif是否会出现在Stack中。这是一个例子:

enter image description here

1 个答案:

答案 0 :(得分:1)

表视图未动态更新的主要原因是NSFetchedResultsController在发生更改时使用委托进行通知。您需要设置该委托self.fetchedResultsController.delegate = self,然后添加委托方法。

以下link to an example用于管理UITableView NSFetchedResultsController

更新

实施这些NSFetchResultsController委托方法,以允许您的表格动态更新。

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath: (NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

通常,这些方法包含用于更新表格的样板代码,您也可以在上面的链接中找到它。