Cannot refresh cell textLabel in tableView - ios

In my iOS app, I want to fresh the entire contents of a tableView when the viewController is loaded. Each cell of a tableView has a textLabel that is the name of a step object.
I've ensured that when I return to the viewController, the correct stepNames are loaded (I know this by logging the names of the steps). However, the name of the step is not updated in the tableView.
How can I ensure that the labels of the tableView cells are loading properly?
How I try to trigger a refresh of the TableView:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
if(reloadSteps == YES){
NSLog(#"reloading steps");
NSData * stepsData = [NSData dataWithContentsOfURL:stepsURL];
[self fetchProjectSteps:stepsData];
[self.projectInfo reloadData];
int numRows = [stepNames count];
NSLog(#"numRows %i", numRows);
for(int i =0; i<numRows; i++){
[self tableView:self.projectInfo cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
}
}
}
How each cell of the tableView is rendered:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"in cellForRowAtIndexPath");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"StepCell"];
}
if (indexPath.row ==0) {
cell.textLabel.font = [UIFont systemFontOfSize:16];
cell.textLabel.textColor = [UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0];
cell.textLabel.text = #"Project Description";
cell.textAlignment = NSTextAlignmentCenter;
} else {
cell.userInteractionEnabled = YES;
cell.textLabel.font = [UIFont systemFontOfSize:16.0];
cell.textLabel.text = [stepNames objectAtIndex:indexPath.row];
NSLog(#"textLabel: %#", cell.textLabel.text); // THIS IS CORRECT, BUT DOES NOT APPEAR TO BE UPDATED IN THE TABLEVIEW
if(![[stepImages objectAtIndex:indexPath.row] isEqual: #""]) {
cell.accessoryView = [stepImages objectAtIndex:indexPath.row];
}
}
return cell;
}
Here is my header file:
#interface EditProjectViewController : UIViewController <UIActionSheetDelegate, UITableViewDelegate, UITableViewDataSource, UIAlertViewDelegate>{
#property (strong,nonatomic) IBOutlet UITableView *projectInfo;
}
and then in my implementation file:
-(void) viewDidLoad{
self.projectInfo = [[UITableView alloc]init];
self.projectInfo.delegate = self;
}

Delete all this:
int numRows = [stepNames count];
NSLog(#"numRows %i", numRows);
for(int i =0; i<numRows; i++){
[self tableView:self.projectInfo cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
}
Your reloadData call will call cellForRowAtIndexPath: for every cell in your table view. Just make sure you're returning stepNames.count for numberOfRowsInSection:.
EDIT
I've looked over your updated code. A couple things (including what your problem most likely is):
Your projectInfo outlet should be weak, not strong (since it's an IBOutlet)
Even though you have your table view linked up in the interface file, you're initializing it in viewDidLoad, creating a new instance
Change the following:
-(void) viewDidLoad{
self.projectInfo = [[UITableView alloc]init];
self.projectInfo.delegate = self;
}
To this:
-(void) viewDidLoad{
self.projectInfo.dataSource = self;
self.projectInfo.delegate = self;
}

Related

How to stop Custom cell contain strong label from overwriting the contents?

the Problem is when using strong label type :KILabel to can detect # and #.
after the cell number 10 it keep the value of cell 1 and 11 and so one 2 and 12
it over write the text on each other.
I know the problem from dequeueReusableCellWithIdentifier but how can solve it the rest of feel controls working well just this label.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CommentCell *cell;
CommentsModels * mycomment = [_CommentsModelsArray objectAtIndex:indexPath.row];
if([mycomment.CommentType integerValue] == 2)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"CommentCellImage"];
}else{
cell = [tableView dequeueReusableCellWithIdentifier:#"CommentCell"];
}
// CommentCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CommentCell"];
if (!cell)
{
if([mycomment.CommentType integerValue] == 2)
{
[ tableView registerNib:[UINib nibWithNibName:#"CommentCellImage" bundle:nil]forCellReuseIdentifier:#"CommentCellImage"];
cell = [ tableView dequeueReusableCellWithIdentifier:#"CommentCellImage"];
}else{
[ tableView registerNib:[UINib nibWithNibName:#"CommentCell" bundle:nil]forCellReuseIdentifier:#"CommentCell"];
cell = [ tableView dequeueReusableCellWithIdentifier:#"CommentCell"];
}
}
cell.commentimage.image = nil;
[cell setcell:[_CommentsModelsArray objectAtIndex:indexPath.row]];
cell.commentsViewController = self;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
the setcell function
- (void) setcell:(CommentsModels*)comment{
User *user = [[HelpManager sharedHelpManager] applicationUser];
UserId = user.userId;
_generalcomment = comment;
if ( _generalcomment.Comment.length > 0) {
KILabel *label;
label = NULL;
label = nil;
label = [[KILabel alloc] initWithFrame:CGRectMake(76,66, 180, 14)];
label.taggedUsers = comment.TaggedUsers;
NSString *labelText = _generalcomment.Comment;
for (TaggedUser *user in comment.TaggedUsers) {
NSString *replacedText = [NSString stringWithFormat:#"(#%#)%#",user.UserName,user.FullName];
NSString *tagText = [NSString stringWithFormat:#"#%#",user.UserName];
labelText = [labelText stringByReplacingOccurrencesOfString:tagText withString:replacedText];
}
label.text = labelText;
label.tag = 1010;
label.font = [UIFont systemFontOfSize:12];
label.textColor = [UIColor lightGrayColor];
label.automaticLinkDetectionEnabled = YES;
label.linkDetectionTypes = KILinkTypeOptionUserHandle | KILinkTypeOptionHashtag;
label.userHandleLinkTapHandler = ^(KILabel *label, NSString *string, NSRange range) {
TaggedUser *selectedUser = nil;
for (TaggedUser *user in comment.TaggedUsers) {
if ([string containsString:user.UserName] && [string containsString:user.FullName]) {
selectedUser = user ;
break;
}
}
if (selectedUser) {
ProfileViewController *profileViewController = [STORYBOARD instantiateViewControllerWithIdentifier:#"ProfileViewController"];
profileViewController.ProfileUserId = selectedUser.Id;
if ( self.commentsViewController != nil)
{
[self.commentsViewController.navigationController pushViewController:profileViewController animated:YES];
}
else{
[_postandCommentsViewController.navigationController pushViewController:profileViewController animated:YES];
}
}
};
label.hashtagLinkTapHandler = ^(KILabel *label, NSString *string, NSRange range) {
SearchMasterViewController *searchMasterViewController = [STORYBOARD instantiateViewControllerWithIdentifier:#"SearchMasterViewController"];
searchMasterViewController.searchText = string;
if ( self.commentsViewController != nil)
{
[self.commentsViewController.navigationController pushViewController:searchMasterViewController animated:YES];
}
else{
[_postandCommentsViewController.navigationController pushViewController:searchMasterViewController animated:YES];
}
};
label.urlLinkTapHandler = ^(KILabel *label, NSString *string, NSRange range) {
// Open URLs
[self attemptOpenURL:[NSURL URLWithString:string]];
};
[label adjustFrameSize];
[self.contentView addSubview:label];
}
The code has a few problems.
1) register the nibs when you're setting up views, as early as viewDidLoad
// in the view controller that is the table's datasource
// assumes you have an outlet setup in IB to the table view
#property(weak,nonatomic) IBOutlet UITableView *tableView;
// ...
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"CommentCellImage" bundle:nil]forCellReuseIdentifier:#"CommentCellImage"];
[self.tableView registerNib:[UINib nibWithNibName:#"CommentCell" bundle:nil]forCellReuseIdentifier:#"CommentCell"];
// plus whatever else you do in viewDidLoad
}
2) next, you can simplify and modernize your cellForRowAtIndex as follows
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CommentsModels * mycomment = [_CommentsModelsArray objectAtIndex:indexPath.row];
NSInteger type = [mycomment.CommentType intValue];
NSString *identifier = (type == 2)? #"CommentCellImage" : #"CommentCell";
CommentCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.commentimage.image = nil;
[cell setcell:[_CommentsModelsArray objectAtIndex:indexPath.row]];
cell.commentsViewController = self;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
3) Lastly, the setcell: should factor out the label creation and only create the label conditionally, if the cell doesn't already have one (after the first display of the table, all of the cells will).
// in CommentCell.m
- (UILabel *)theLabel {
KILabel *label = (KILabel *)[cell viewWithTag:1010];
if (!label) { // only create one if its not there
label = [[KILabel alloc] initWithFrame:CGRectMake(76,66, 180, 14)];
label.tag = 1010;
// everything else you do to create the label goes here,
// but NOT anything variable relative to the model, so
// for example, not label.text = anything
[self.contentView addSubview:label];
}
return label;
}
Now setcell: is slightly saner, just getting the (probably already created) label and changing things about only that change for the given model item at the given row.
- (void) setcell:(CommentsModels*)comment {
User *user = [[HelpManager sharedHelpManager] applicationUser];
UserId = user.userId;
_generalcomment = comment;
if ( _generalcomment.Comment.length > 0) {
KILabel *label = [self theLabel];
NSString *labelText = _generalcomment.Comment;
// I didn't try to understand the following code, but it looks
// potentially too slow for configuring a table view cell.
// consider doing this calculation just once and caching the result in the model
for (TaggedUser *user in comment.TaggedUsers) {
NSString *replacedText = [NSString stringWithFormat:#"(#%#)%#",user.UserName,user.FullName];
NSString *tagText = [NSString stringWithFormat:#"#%#",user.UserName];
labelText = [labelText stringByReplacingOccurrencesOfString:tagText withString:replacedText];
[label adjustFrameSize];
}
}
}
because dequeueReusableCell function return old cell that contain old label
so You can remove label before load new item.
- (void) setcell:(CommentsModels*)comment {
[[self.contentView viewWithTag:1010] removeFromSuperview];
//... your cuttom code here
}

How come my UITableView is repeating rows after 5 rows?

I have 7 rows in my database. I confirmed that all of the data is successfully coming over to the iOS side by NSLog the postArray which gives 7. However when I run my app, it will only display the first 5 rows, and then the first 2 rows instead of the 6th and 7th row from my database. Also when I NSLog the actual text from my 6th and 7th text view the correct text is in there... Why is it repeating after 5 rows? Thank you. Here is my code:
#import "DailyViewController.h"
#import "Post.h"
#interface DailyViewController ()
#end
#implementation DailyViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// View background
[self.view setBackgroundColor:[UIColor colorWithRed:(255/255.0) green:(221/255.0) blue:(85/255.0) alpha:1.0f]];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://example.org/getPosts.php"]];
NSData *data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
postArray = [[NSMutableArray alloc] init];
for(int i = 0; i < jsonArray.count; i++)
{
NSString *nickname = [[jsonArray objectAtIndex:i] objectForKey:#"nickname"];
NSString *squeal = [[jsonArray objectAtIndex:i] objectForKey:#"squeal"];
[postArray addObject:[[Post alloc] initWithNickname:nickname andSqueal:squeal]];
}
viewArray = [[NSMutableArray alloc] init];
for(int i = 0; i < postArray.count; i++)
{
Post *postObject;
postObject = [postArray objectAtIndex:i];
UILabel *nicknameLabel = [[UILabel alloc]initWithFrame:CGRectMake(30, 15, 320, 30)];
nicknameLabel.text = postObject.nickname;
nicknameLabel.font = [UIFont boldSystemFontOfSize:20];
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(25, 42, 320, 0)];
textView.font = [UIFont systemFontOfSize:15];
textView.text = postObject.squeal;
textView.editable = false;
[textView setScrollEnabled:false];
[textView sizeToFit];
[textView layoutIfNeeded];
UIView *view = [[UIView alloc] initWithFrame: CGRectMake (0, 0, 320, 30+textView.frame.size.height)];
[view addSubview:nicknameLabel];
[view addSubview:textView];
[viewArray addObject:view];
}
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return postArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell.contentView addSubview:[viewArray objectAtIndex:indexPath.row]];
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIView *view = [viewArray objectAtIndex:indexPath.row];
return view.frame.size.height+30;
}
#end
UITableView reuses the cells with the same reuse identifier, which means that when you scroll so that a row is scrolled out of the visible area, it will be used to show new rows. That's why when your 1st and 2nd rows were scrolled out of the view, they were used to show the 5th and 6th row.
You need to modify how you load cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// Add and setup views here.
}
//Add content to view here
// e.g. cell.textLabel.text = #"Some text";
return cell;
}
BTW You can use the property textLabelof UITableViewCellinstead of creating a new label and adding it as as subview. If you need to have more control over your custom cell, then you should create a custom class and use a Storyboard file or a Xib file.
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
else
{
[[cell.contentView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
}
[cell.contentView addSubview:[viewArray objectAtIndex:indexPath.row]];
In your cellForRowAtIndexPath method, you are adding a subview to the cell's content view only if the cell is being initialized for the first time.
Rather, you should add/replace the subview on each call to cellForRowAtIndexPath.

Make Change in TableViewCell

I'm working on the TableView, and I have used the label on the TableViewCell and on the button click I want to hide the label from all cells in my table,
In the label I have set the tag:
label.tag = indexPath.row+1;
And on the button click I am using the code like this:
for (int i = 0; i < Array.count; i++)
{
[[self.view viewWithTag:i+1] setHidden:YES];
}
But from my code the label is hiding only from the last cell not all the others.
You can simply do this with another way.
First you need to declare a BOOL in your class
#property(assign,nonatomic) BOOL hideLabels;
Next in your button action handler method, set this YES
In your cellForRowAtIndexPath, check whether hideLabels is YES, if yes, the hide labels using code.
cell.yourLabel.hidden = hideLabels;
Now reload the table after setting hideLabels as YES
[self.tableView reloadData];
for(id object in tableView.subviews)
{
if([object isKindOfClass:[UILabel class]])
{
UILabel *label = (UILabel *) object;
[[label setHidden:YES];
}
}
In your ViewController.h
BOOL isLabelHidden;
in ViewController.m
- (void)viewDidLoad
{
isLabelHidden = FALSE;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TableCell";
UILabel *lbl;
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = nil;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if(isLabelHidden)
[lbl setHidden:YES];
else
[lbl setHidden:NO];
}
in you button clicked method
- (void)buttonClicked
{
isLabelHidden = TRUE;
[tableView reloadData];
}
You should first get the reference to the UITableViewCell and then you can remove the labels in them.
First of all get the reference to all the cells in your tableview as follows:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
{
[cells addObject:[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
}
}
And now iterate through those cells in cells Array to hide the label view,
for (int i = 0; i < cells.count; i++)
{
[[[cells objectAtIndex:i] viewWithTag:i+1] setHidden:YES];
}
Source:How can I loop through UITableView's cells?

scrollViewDidScroll method not giving reference to all scrollviews from table view

I have created tableView with custom cells that contain image view and scrollView. All scroll views contain labels wider than screen bounds, so when I scroll to left/right I want all scrollViews to scroll in same direction. Problem is I don't know how to get reference to each scrollView in scrollViewDidScroll method.
my viewController class:
#import "EPGViewController.h"
#interface EPGViewController (){
NSArray *EPGList;
int scrollPositionX;
}
#end
#implementation EPGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = false;
EPGList = [NSMutableArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12", nil];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return EPGList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *hlCellID = #"EPGCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:hlCellID];
if(cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:hlCellID];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
UILabel *label = (UILabel *)[cell viewWithTag:15];
label.text = EPGList[indexPath.row];
UIScrollView *scrolView = (UIScrollView *)[cell viewWithTag:16];
scrolView.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0];
scrolView.delegate = self;
scrolView.tag = indexPath.row+101;
scrolView.scrollEnabled = YES;
scrolView.contentSize = CGSizeMake(scrolView.frame.size.width,scrolView.frame.size.height);
[scrolView setShowsHorizontalScrollIndicator:NO];
[scrolView setShowsVerticalScrollIndicator:NO];
int i=0;
for(i=0;i<15;i++){
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0+i*100, 0, 100, 100)];
label.text = #"HELLO";
label.textColor = [UIColor blackColor];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont fontWithName:#"ArialMT" size:18];
[scrolView addSubview:label];
scrolView.contentSize = CGSizeMake(scrolView.frame.size.width+i*label.frame.size.width,scrolView.frame.size.height);
}
[cell addSubview:scrolView];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80.0;
}
- (void)scrollViewDidScroll:(UIScrollView *)callerScrollView {
scrollPositionX = callerScrollView.contentOffset.x;
//if this is called with table view exit
if (callerScrollView == self.tableView) return;
int indexPath = callerScrollView.tag-101;
NSLog(#"TAG: %d",indexPath);
for (UITableViewCell *cell in self.tableView.visibleCells) {
//TODO: Don’t use tags.
UIScrollView *cellScrollView = (UIScrollView *)[cell viewWithTag:16];
if (callerScrollView == cellScrollView) continue;
cellScrollView.contentOffset = CGPointMake(scrollPositionX, 0);
}
}
#end
EDIT:
I managed to solve my problem by deleting line where I add different tags to scrollviews in table view. now I just set offset to scrollview with tag 16.
There are multiple wrong things in your code. Here is better implementation:
- (void)scrollViewDidScroll:(UIScrollView *)callerScrollView {
scrollPositionX = callerScrollView.contentOffset.x;
if (callerScrollView == self.tableView) return;
for (UITableViewCell *cell in self.tableView.visibleCells) {
//TODO: Don’t use tags.
UIScrollView *cellScrollView = (UIScrollView *)[cell viewWithTag:16];
if (callerScrollView == cellScrollView) continue;
cellScrollView.contentOffset = CGPointMake(scrollPositionX, 0);
}
}
Some additonal notes:
This method will be called by table view too, so you will have to check that.
Don’t use any indexes, just plain iteration.
I used checking of scrollViews, but basically there it would be OK without it.
Using tags to identify subviews is not a good idea.
Don’t call reloadData every time!
You should use [tableView visibleCells]; in order to get all cells that are visible at this moment.
You could use UITableView's visibleCells method to get all visible cells and get your scrollviews from there (you can use viewwithTag like you do, but on all cells).
Then you would have to remember to adjust the scrollview position as cells are reused/recreated - probably keep the scrolled offset as a property of your View Controller.
The problem is that you're using dequeueReusableCellWithIdentifier rather than just looping through the cells that have already been displayed.
Do something like:
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
{
if (!(indexPath.section == j && indexPath.row == i))
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
UIScrollView *scrollView = (UIScrollView *)[cell viewWithTag:16];
scrollView.contentOffset = CGPointMake(position_x, scrollView.frame.size.height);
}
}
}

Update UItableView in viewWillAppear?

I have problem with my UItableview that when I use viewWillAppear for retrieving updated data each time table is viewed this gives me exception .
Please can any one help me on how to refresh tableview in viewWillAppear so that it will be updated before CellforrowAtindexPath is called ?
Here is my code for viewWillAppear:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self.tableView reloadData];//table was filled in viewDidLoad.
}
Here is CellforrowAtindexPath` : (The exception is on mainArray which means that there is conflict in updating table through viewWillAppear and calling cell ):
//Methods to retrive all selected words , thier sound and picture for the mother
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifer = #"Cell";
UITableViewCell *cell= [ tableView dequeueReusableCellWithIdentifier:CellIdentifer];
cell.textLabel.font = [UIFont systemFontOfSize:17.0];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifer];
}
cell.textLabel.font = [UIFont systemFontOfSize:17.0];
UILabel *label ;
label=(UILabel *)[cell viewWithTag:1];
NSString *value = [[self.mainArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
label.text = value;
label.textAlignment=NSTextAlignmentRight;
label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
//self.tableView.separatorColor = [UIColor blackColor];TRY TO SEPARETE BETEWEEN LINES OF TABLE
UIButton *butt =(UIButton *)[cell viewWithTag:2];
NSString *value2 = [[self.mainArray2 objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
butt.restorationIdentifier= value2;
[butt addTarget:self action:#selector(play:) forControlEvents:UIControlEventTouchUpInside];
NSString *value3 = [[self.mainArray3 objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:value3];
label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
return cell;
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;{
return self.mainArray.count;
}
if count is 0, table view won't call the other functions.

Resources