【问题标题】:update UITableViewCell from other method从其他方法更新 UITableViewCell
【发布时间】:2015-09-09 04:31:52
【问题描述】:

我在 GG 中搜索了千元以找到 UITableViewCell 的解决方案更新数据,但都显示解决方案是

UITableViewCell *cell=(UITableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];

但是对于所有可见的单元格,该单元格为零。我已经使用 NSNotification 将数据从一种方法发送到 ViewController.m ,而我希望通过 indexPath 将数据更新到单元格的 Reiever 方法。但所有单元格都是 nil 并且不能更新。

这里是我的代码 ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property(nonatomic, strong) IBOutlet UITableView *tableView;

@end 

ViewController.m

@implementation ViewController
{

}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(theReciever:) name:@"theSender" object:nil];

}                
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [recipes count];
}       
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"SimpleTableCell";
    UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
        NSLog(@"cell nil");

    }

    NSString *idgame=@"Gamexyz";
    cell.textLabel.text = idgame;
    cell.tag=indexPath.row;

    return cell;
}

-(void)theReciever:(NSNotification*)notif{

    if([notif.object isKindOfClass:[packeData class]]){

        packeData *data=[notif object];

        NSString *key=data.key;
        NSInteger *index=[key integerValue];
        NSIndexPath *indexPath=[NSIndexPath indexPathWithIndex:index];

        UITableViewCell *cell=(UITableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];

       //UITableViewCell *cell=(UITableViewCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:7 inSection:0]];

        if(cell==nil)
        {
            NSLog(@"cell NULL");
        }else{
            cell.textLabel.text=data.process;
        }

    }else{
        NSLog(@"ERR: object not recognised");
    }

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

任何人都可以帮助我或通过 indexPath 更新 UITableViewCell 中的数据的解决方案示例

【问题讨论】:

  • dequeueReusableCellWithIdentifier 切换为dequeueReusableCellWithIdentifier:forIndexPath:
  • 你有多少节?
  • 尝试在'viewWillAppear'方法上重新加载tableView
  • @BlackRider 我已更改为 UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath]; 但仍有 cell==nil
  • @anhtu 你的意思是我有多少行,如果我有 20 个部分

标签: ios objective-c uitableview


【解决方案1】:

注意:以下只是您可以在新项目中执行的示例

您需要更改数据模型packeData,假设它包含key,因为NSIntager 保存单元格的索引,processNSString,它将进度保存为字符串值例子

packeData.h

#import <Foundation/Foundation.h>

@interface packeData : NSObject
@property (nonatomic, assign) NSInteger key; //holds index
@property (nonatomic, strong) NSString *process; //holds the progress info

@end

packeData.m

#import "packeData.h"

@implementation packeData
- (id)init //simply initialise it 
{
   self = [super init];
   if(self)
   {

   }
   return self;
}

@结束

在你是tableview的视图控制器中,

ViewController.h

#import <UIKit/UIKit.h>
#import "packeData.h"
@interface ViewController : UIViewController <UI TableViewDataSource,UITableViewDelegate>   
@property (weak, nonatomic) IBOutlet UITableView *aTableView;
@property (strong,nonatomic) NSMutableArray *recipes; //array acts as datasource

@end

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad  
{
   [super viewDidLoad];
   // Do any additional setup after loading the view, typically from a nib.
  [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(theReciever:) name:@"theSender" object:nil];

  _recipes = [[NSMutableArray alloc]init]; //initilise your datasource
  for(int j = 0 ;j< 20;j++)
   {
    // for my example i took some values
    //initially put some initial values
    packeData *data = [[packeData alloc] init];
    data.key = j;
    data.process = [NSString stringWithFormat:@"game_name_%d",j];
    [_recipes addObject:data];
  }
 }

 - (void)viewDidAppear:(BOOL)animated
 {
   [super viewDidAppear:animated];
   [NSTimer scheduledTimerWithTimeInterval:0.8 target:self selector:@selector(PostNotification) userInfo:nil repeats:YES];  //just for testing   
 } 

 - (void)PostNotification
 {
   //i am simply posting the notification with some random values
   packeData *data = [[packeData alloc]init];
   data.key = arc4random()%15;
   data.process = [NSString stringWithFormat:@"%ld",( data.key  + 20)];
   [[NSNotificationCenter defaultCenter] postNotificationName:@"theSender" object:data];
 }

- (void)theReciever:(NSNotification *)notif
{
    if([notif.object isKindOfClass:[packeData class]]){

      packeData *data=[notif object];
      NSInteger key=data.key;
      NSInteger index= key;
      //modify the datasource
      packeData *recipes_data = [_recipes objectAtIndex:index]; //get the pocket present in array
      recipes_data.process = data.process; //modify the recipes data

      NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
      UITableViewCell *cell=(UITableViewCell*)[self.aTableView cellForRowAtIndexPath:indexPath];

      if(cell==nil)
      {
         NSLog(@"cell NULL");
      }else
      {
         [self.aTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        //  cell.textLabel.text=data.process; no need u already mofied the content in the datasource this will call the "cellForRowAtIndexPath" method and displays the process in place of game name
     }
     }else{
       NSLog(@"ERR: object not recognised");
     }
 }

  - (void)didReceiveMemoryWarning {
     [super didReceiveMemoryWarning];
     // Dispose of any resources that can be recreated.
  }

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

  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {
    return [_recipes count];
 }

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
   static NSString *simpleTableIdentifier = @"SimpleTableCell";
   UITableViewCell* cell = [self.aTableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    NSLog(@"cell nil"); 
   }
   packeData *idgame= [_recipes objectAtIndex:indexPath.row];
   cell.textLabel.text = idgame.process; //initially contains game name
   cell.tag=indexPath.row;
   return cell;
 }

 @end

编辑

替换以下方法

- (void)PostNotification
 {
   //i am simply posting the notification with some random values
   packeData *data = [[packeData alloc]init];
   data.key = arc4random()%15; //15 change the number of rows
   data.process = [NSString stringWithFormat:@"%ld",( data.key  + arc4random() % 100)];
   [[NSNotificationCenter defaultCenter]      postNotificationName:@"theSender" object:data];  
 }


 - (void)theReciever:(NSNotification *)notif
 {
    if([notif.object isKindOfClass:[packeData class]]){

    packeData *data=[notif object];
    NSInteger key=data.key;
    NSInteger index= key;
    //modify the datasource
    packeData *recipes_data = [_recipes objectAtIndex:index]; //get the pocket present in array
    recipes_data.process = data.process; //modify the recipes data

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
    UITableViewCell *cell=(UITableViewCell*)[self.aTableView cellForRowAtIndexPath:indexPath];

    if(cell==nil)
    {
        NSLog(@"cell NULL");
        [self.aTableView reloadData]; //if cell is not visible then reload the whole table
    }else
    {
        [self.aTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
      //  cell.textLabel.text=data.process; no need u already mofied the content in the datasource this will call the "cellForRowAtIndexPath" method and displays the process in place of game name
    }
    }else{
      NSLog(@"ERR: object not recognised");
   }

 }

编辑 2

至于测试只需更改以下方法,一旦模拟器启动应用程序向下滚动,以便仅更新前 5 行,等待 5 到 10 秒并滚动到顶部,您将看到所有调用都是更新流程相同 5

//scroll down as soon as launches the app and wait for 5 to 10 seconds then scroll to top u will see top 5 cells are updates with progress 5
- (void)PostNotification
{
   packeData *data = [[packeData alloc]init];
   data.key = arc4random()%5; //only top 5 cells are modify other wont modify
   data.process = [NSString stringWithFormat:@"%ld",5];//updates with some same progress lates give it as 5 //( data.key  + arc4random() % 100)];
  [[NSNotificationCenter defaultCenter] postNotificationName:@"theSender" object:data];
}

从上面的测试中你会看到前 5 个单元格是更新的,即使它们不可见

【讨论】:

  • 感谢您的解决方案。但是当单元格滚动和隐藏时, textlabel.text 将被更新。我想更新表格视图中可见的单元格。请帮帮我
  • 取决于通知对象,它可能包含可见单元格或不可见单元格的索引,如果单元格可见则将看到单元格进度,否则不会出现但也更新该单元格
  • 我越来越多地尝试重新检查,单元格可见并且通知对象包含索引。但是如果滚动表格,数据将被更新,否则不会
  • 你的意思是如果单元格不可见,则单元格不会更新
  • 您的支持让我非常激动。你的意思是添加[self.aTableView reloadData]; 并且单元格不可见然后重新加载表格。我在新项目中按照您的指示进行了编辑。它仍然无法正常工作,单元格在不可见然后可见后仍然更新
【解决方案2】:

除了cellForRowAtIndexPath,您不能设置任何单元格控制器的值,您必须使用数组填充 UITableViewCell 数据,然后当您想要更新单元格中的数据时,根据数据更新您的数组,然后像这样更新 UITableView 的单个单元格。

[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPathOfYourCell] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates]; 

【讨论】:

    【解决方案3】:

    只需指定行的索引路径并重新加载...

    NSIndexPath* path = [NSIndexPath indexPathForRow:3 inSection:0];
    NSArray* rowsToReload = [NSArray arrayWithObjects:path, nil];
    [tableView reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationNone];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-23
      • 1970-01-01
      相关资源
      最近更新 更多