I am facing a weird issue and I am sure I am doing something wrong. In my UITableViewController class I have a function as follows:
-(void)EERefreshView
{
NSLog(#"App delegate requested the view be refreshed");
[self loadEventsFromDB];
for(int a=0;a<eventsList.count;a++)
{
DB_EEEvent *event = (DB_EEEvent*)eventsList[a];
UITableViewCell *cell =
[self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
//NSLog(#"CellID %#", cell.reuseIdentifier);
//get references to the UI components
UILabel *lblTitle = (UILabel*)[cell.contentView viewWithTag:5];
UILabel *lblDate = (UILabel*) [cell.contentView viewWithTag:6];
UIImageView *imgEvent = (UIImageView*)[cell.contentView viewWithTag:7];
//set values
lblTitle.text = event.name;
lblDate.text = [NSString stringWithFormat:#"%# - %#",
event.startdate,event.enddate];
AppDelegate *del = [AppDelegate sharedAppDelegate]; //need this to get the BaseURL
// Here we use the new provided setImageWithURL: method to load the web image
NSString * imageURL =[[NSString alloc] initWithFormat:#"http://%#%#",del.api.BaseURL,event.logo];
NSString* webStringURL = [imageURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:webStringURL];
[imgEvent setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
//do somethign when image call completes
}];
[eventsListCells addObject:cell];
if(a == selectedEvent)
{
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[tblEventsList reloadData];
});
}
This function loads an array with UITableViewCell objects which is then used later on by
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell data
NSLog(#"IndexPathRow: %d", indexPath.row);
UITableViewCell *cell = (UITableViewCell*)eventsListCells[indexPath.row];
return cell;
}
However when the cell is loaded lblTitle and lblDate have no text displaying in them. But when I tap on a cell it then displays the text in the labels. So this means that the data is there but its not being refresh when initially created. I suspect this might have something to do with threads but I am not an expert on the subject and would appreciate any help that I can get.
I see what is bothering you and why you created this method, but you don't need it. The only reason why you need back thread is your image loading so that should be thrown in bkg. thread and the rest of the code should be in -
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.
U really don't need to pre create cells, and U cant cause they are reusable. For example if you have 50 elements in eventsList and room for only 5 cell on your screen you cant create 50 cells cause the code will create only 5+1 and reuse them as they appear on the screen, so every element of your eventsList will use one of those 5 cells and on the other side every cell will be a host for 10 different elements from your eventsList array. So as you can see your code doesn't make much sense...
The second function you mentioned in your question is the function that is called to populate the table with data. When you call [tblEventsList reloadData]; your app just calls the (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. So this method needs to be outputting data back to the table. A very simple example is below. Also, make sure your table delegate and data source are set.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell.
cell.textLabel.text = [self.your_data_source objectAtIndex:[indexPath row]];
return cell;
}
Related
I am using Objective C and Parse. I have a UITableView that displays photos from Parse. The first 10 cells load then you can tap load more for the next 10 cells and so on. My issue is in the same class that I am getting the photo, I also want to display the caption column. The first 10 cells show the caption correctly, it's when I page to the next 10 cells that the captions start repeating. The photos do not repeat so I'm not sure why the captions do. Below is my code that loads the UITableView:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
if (indexPath.section == self.objects.count) {
// this behavior is normally handled by PFQueryTableViewController, but we are using sections for each object and we must handle this ourselves
UITableViewCell *cell = [self tableView:tableView cellForNextPageAtIndexPath:indexPath];
return cell;
}
else {
ESPhotoCell *cell = (ESPhotoCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ESPhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell.mediaItemButton addTarget:self action:#selector(didTapOnPhotoAction:) forControlEvents:UIControlEventTouchUpInside];
}
cell.mediaItemButton.tag = indexPath.section;
//The below line of code displays the black square where the photo would be.
cell.imageView.image = [UIImage imageNamed:#"PlaceholderPhoto"];
if (object) {
//The below line displays the users photo on the timeline.
//The following 2 lines is what fills the display cell that shows the photo.
cell.imageView.clipsToBounds = YES;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
//The below line is what displays the image on the home timeline.
cell.imageView.file = [object objectForKey:kESPhotoPictureKey];
[cell.imageView loadInBackground];
//Below is what I am trying to display the captions
NSString *caption = [object objectForKey:#"caption"];
if (caption != nil) {
cell.captionText.text = [object objectForKey:#"caption"];
}
}
return cell;
}
}
Any help to this issue would be appreciated as I am fairly new to mobile development.
I'm working on an iOS storyboard app with a UITableView and dynamic cells. I want a segmented control to determine which type of cell populates the tableView contents.
Here is The viewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
[_reelsOrAllSegmentedControl addTarget:self
action:#selector(segmentedControlTouched)
forControlEvents:UIControlEventValueChanged];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier0 = #"cellType1";
NSString *CellIdentifier1 = #"cellType2";
long row = [indexPath row];
if([_segmentedControl isEnabledForSegmentAtIndex:0])
{
CellType1 *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier0
forIndexPath:indexPath];
NSArray *folderArray = [[NSArray alloc] initWithArray:[[UserSession sharedSession] userFolders]];
[[cell titleTextView] setText:(NSString*)folderArray[row][#"title"]];
else if([_segmentedControl isEnabledForSegmentAtIndex:1]){
CellType2 *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier1
forIndexPath:indexPath];
NSArray *postArray = [[NSArray alloc] initWithArray:[[UserSession sharedSession] userPosts]];
cell.captionTextView.text = postArray[row][#"caption"];
return cell;
}
-(void)segmentedControlTouched
{
NSLog(#"touch");
[self.tableView reloadData];
}
Every time I switch the segmented control, the first block of the if is run. Shouldn't the second one be run when the table is refreshed?
You would be better off creating two separate classes implementing UITableViewDataSource, and setting the table view's dataSource appropriately when the user changes the selected segment.
But anyway, you can get your code working by looking at the control's selectedSegmentIndex property:
if(_segmentedControl.selectedSegmentIndex == 0) {
CellType1 *cell = [tableView
... etc.
I have an NSDictionary objectreturned from my server. I am using it to populate information on a UITableViewController. My issue is that when I am processing each object returned, it seems to duplicate, lets say I get 2 objects returned. It will make 2 table cells but with only the first object's data. So lets say the title section from both objects is "yes" and "no". It would populate the list with the first object title so it would show, yes and yes.
Here is what happens:
Controller is loaded:
- (void)viewDidLoad
{
[super viewDidLoad];
// MAKE REQuEST TO SERVER
[self makeRequests];
}
runs the request from server which stores information as follow:
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:returnData //1
options:kNilOptions
error:&error];
self.googlePlacesArrayFromAFNetworking = [json objectForKey:#"requested_data"];
[self.tableView reloadData];
than the cellForRowAtIndexPath runs:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"timelineCell";
FBGTimelineCell *cell = (FBGTimelineCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[FBGTimelineCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.usernameLabel.text = [_googlePlacesArrayFromAFNetworking[indexPath.row] objectForKey:#"name"]; <!-- here is where the title example I was talking about happens
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell initTimelineCell];
}
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:#"%d.jpg", indexPath.row]];
cell.photoView.image = img;
return cell;
}
Here is my googlePlacesArr...
#property (strong, nonatomic) NSArray *googlePlacesArrayFromAFNetworking;
Here is my numberOfRowsInSection
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.googlePlacesArrayFromAFNetworking count];
}
Suggestions thoughts? Let me know if you need anything else.
UPDATE:
Also I think its important to note I am using this:
https://github.com/Seitk/FB-Gallery
As a base for populating my returned data.
This usually happens when the cell gets recycled if your tableView:cellForRowAtIndexPath: method fails to set some of the members of recycled objects.
That is precisely what happens in your code: when the cell is recycled, you never set its usernameLabel.text, so the recycled value may be shown multiple times.
You should move the code that sets up cell's properties outside of the if statement to fix this problem:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"timelineCell";
FBGTimelineCell *cell = (FBGTimelineCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[FBGTimelineCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell initTimelineCell];
}
// This line is moved from the "if" statement
cell.usernameLabel.text = [_googlePlacesArrayFromAFNetworking[indexPath.row] objectForKey:#"name"];
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:#"%d.jpg", indexPath.row]];
cell.photoView.image = img;
return cell;
}
Try this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* /////// Custom code ////// */
cell.usernameLabel.text = [_googlePlacesArrayFromAFNetworking[indexPath.row] objectForKey:#"your_key_name"];
}
I have a problem with data being displayed in a UITableViewCell I have created.
I have a CoreData Model which I have a custom Cell which I am loading from a Xib. The layout loads correctly and the correct number of cells are generated. The problem comes when updating the button.titleLabel.text and description.
Here is my uitableview and uitableviewcell related code:
#pragma mark - UITableViewDatasource Methods.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [pointsHistoryItems count];
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d",indexPath.row];
PointsHistoryItemCell* cell = (PointsHistoryItemCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return [self createCustomCell:cell cellForRowAtIndexPath:indexPath];
}
- (PointsHistoryItemCell *)createCustomCell:(PointsHistoryItemCell *)cell cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (cell == nil)
{
cell = (PointsHistoryItemCell *)[[[NSBundle mainBundle] loadNibNamed:#"PointsHistoryItemCell" owner:self options:nil] objectAtIndex:0];
}
AwesomePointsHistoryItem *aphi = (AwesomePointsHistoryItem *)[pointsHistoryItems objectAtIndex:indexPath.row];
cell.description.text = aphi.description;
NSString* pointsText = [NSString stringWithFormat:#"%# Points", [aphi.points stringValue]];
[cell.button.titleLabel setText:pointsText];
NSLog(#"is reaching createCustomCell");
NSLog(#"points %#", cell.button.titleLabel.text);
return cell;
}
the log prints:
is reaching createCustomCell
points 600 Points
However.. The cell.button.titleLabel.text does not update!
What am I doing wrong?
Use
[cell.button setTitle: pointsText forState: UIControlStateNormal];
instead of
[cell.button.titleLabel setText:pointsText];
Note : hope cell.button is a UIButton
I've checked a few other questions but still can't figure out why this is happening. All I know is after using the description code from this question the cell's value is null. I've set the delegate and datasource of the table correctly and I can't see where this is going wrong.
If I set the return value of the following method to 0, no error occurs because the cellForRowAtIndexPath method doesn't really take place. So if I set it as 1 (as it should be) it'll then throw the error. I've synthesized the NSArray and checked that its populated (although that shouldn't matter I guess) and basically what is meant to happen is I press a button that searches and then places the results in the table. So before this the tableview is empty.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
Here's the cellForRowAtIndexPath method itself. I've tried just using the basic template method too, which still throws the same error.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
NSDictionary *aResult = [results objectAtIndex:[indexPath row]];
NSLog(#"RESULTS IN TABLE %i", [results count ]);
id key = [results objectAtIndex:[indexPath row]];
resultTitle.text=#"Hello";
NSURL *url = [NSURL URLWithString:[aResult objectForKey:#"url"]];
NSData *data = [NSData dataWithContentsOfURL:url];
cell.imageView.image = [UIImage imageWithData:data];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[theTableView reloadData];
return cell;
}
I've no idea what is wrong. I've used tableviews before and have compared this project to others to see if I've missed something, but I can't see any real differences.
you are not initisialing the cell if nil is returned from the dequeue method
change
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
to
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
You do not have a method to return the number of rows in section 0 - this is a required data source method (in this case).