gpt4 book ai didi

ios - 自定义 UITableView 单元格中的 UILabel 未随核心数据更改更新

转载 作者:行者123 更新时间:2023-11-29 12:32:25 25 4
gpt4 key购买 nike

我正在尝试构建一个游戏计分应用程序,该应用程序使用带有玩家照片、姓名、按钮等的自定义表格单元格......在点击我的保存方法的表格 View 的自定义单元格中直接有添加/减去按钮,并将其存储回该特定用户的核心数据中。

问题是屏幕上的分数没有更新和反射(reflect)变化。对 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 进行了报告...但是 View 仍然没有改变。

操作是增加分数,然后我使用 [self configureCell:cell atIndexPath:path]; 重置单元格在那里...负责将文本发送到的方法显示...NSLog 正在显示 2014-12-04 22:40:40.199 appName[7153:150248] Tim 的分数:4 而显示仍然只显示 3。

我知道这是一些愚蠢的菜鸟举动......我只是在做一些我无法弄清楚的错误。这是修改后的代码片段。

- (NSFetchedResultsController *)fetchedResultsController {

if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Players"
inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];

NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"playerName" ascending:YES];

[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:_managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Root"];

self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;

NSError *error;
NSArray *results = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
_playerArray = [[NSMutableArray alloc]initWithArray:results];
NSLog(@"_playerArray count: %i", [_playerArray count]);

return _fetchedResultsController;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}

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

static NSString *cellIdentifier = @"playerCell";
ScoringCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[ScoringCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier];
}

[self configureCell:cell atIndexPath:indexPath];
return cell;
}

- (void)configureCell:(ScoringCell *)cell atIndexPath:(NSIndexPath *)indexPath {

Players *player_info = [_fetchedResultsController objectAtIndexPath:indexPath];
NSSet *scoreSet = player_info.scores;

NSString *cell_score;
for (Scoring *scoreObj in scoreSet) {
cell_score = [scoreObj.score stringValue];
}

NSLog(@"Score for %@: %@", player_info.playerName, cell_score);

if (cell_score != nil) {
cell.lblPlayerScore.text = cell_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:@"demo_playerb"];

[self resetViews];
NSLog(@"\n");
}

- (IBAction)increaseScore:(id)sender {

NSLog(@"PageContentViewController: increaseScore()");
UIButton *senderButton = (UIButton *)sender;
int selectedPlayerInt = senderButton.tag;
NSIndexPath *path = [NSIndexPath indexPathForRow:senderButton.tag inSection:0];

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

-(void)updateRowScore:(Players *)player_info :(NSString *)modifier :(int)selectedPlayerInt :(NSIndexPath *)path {

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];


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


[self configureCell:cell atIndexPath:path];
[self resetViews];
}

------------

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

enter image description here

最佳答案

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

这是一个link to an example用于使用 NSFetchedResultsController 管理 UITableView

更新

实现这些 NSFetchResultsController 委托(delegate)方法以允许您的表动态更新。

- (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

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

关于ios - 自定义 UITableView 单元格中的 UILabel 未随核心数据更改更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27275027/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com