Objective-C, iOS SDK, How to save UITableView Cell image checkmark - objective-c

I'm trying to save the image state of the cell as to when the user exits the app or leaves the view, the image is still saved. I'm thinking NSUserDefaults maybe, what's the best way?
Thanks.
Currently I have this:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell.imageView.image == [UIImage imageNamed:#"checkboxfull.png"]){
cell.imageView.image = [UIImage imageNamed:#"checkboxblank.png"];
}else if(cell.imageView.image == [UIImage imageNamed:#"checkboxblank.png"])
{
cell.imageView.image = [UIImage imageNamed:#"checkboxfull.png"];
// [alert show];
}
}

It really depends on how many cells you have that you're trying to save the content of. If it's a few, it's not a big deal to do in NSUserDefaults, but if it's lots more, maybe Core Data would be a better solution for you.
If you wanted to use NSUserDefaults, you probably want to set a BOOL in there to indicate whether the checkbox is on or off (since you only have two states). So:
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"someUniqueIdentifier"];
Hope this helps.

I would probably use NSUserDefaults for a few things, but I wouldn't save them individually. I would probably store each cell in an array. It will make saving multiple cells much easier.
NSMutableArray *checkState = [[NSArray alloc] init];
if([cell.imageView.image highlighted]) {
[checkState addObject:[NSNumber numberWithBool:YES]];
} else
[checkState addObject:[NSNumber numberWithBool:NO]];
Then when you load your table:
NSArray cellState = [NSUserDefaults standardDefaults] objectForKey:#"yourSavedKey"];
[cell.imageView.image setHighlighted:[cellState objectAtIndex:indexPath.row]];

Related

Reloading searchResultsTableView

I have, in my main tableView, some custom cells (cells with an imageView, basically).
The imageView is set only if a value on my plist is false. Then, when it's true, the imageView is nil.
Basically when the user enters the detailView, the value is set to YES and the cell.imageView is nil.
And it's okay, it works
I'm using a searchDisplayController, when i search for something that has a cell.imageView, going into the detailView and then coming back to the searchResultsTable, the cell has still the image, while it shouldn't, but the main tableView has the correct cell (so, with no image).
I thought that it could depend on searchResultsTableView, but i'm not sure.
I tried with
[self.searchDisplayController.searchResultsTableView reloadData];
with no effect.
How could i reload the searchResultsTableView so that it shows the right cells, those with the image and those that don't have the image anymore?
Any help appreciated!
EDIT
This is my cellForRowAtIndexPath method:
- (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] autorelease];
}
NSArray *rows;
if (tableView == self.searchDisplayController.searchResultsTableView) {
rows = filteredList; //for search
} else {
NSDictionary *section = [localSortedTips objectAtIndex:indexPath.section];
rows = [section objectForKey:#"Rows"];
}
NSDictionary *item = [rows objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:#"name"];
if ([[item valueForKey:#"isRead"] boolValue] == NO) {
cell.imageView.image = [UIImage imageNamed:#"unread.png"];
} else {
cell.imageView.image = nil;
}
cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
return cell;
}
If I understood you right, then you can have a workaround but searching again with the same search string:
if (self.searchDisplayController.active) {
self.searchDisplayController.searchBar.text = self.searchDisplayController.searchBar.text;
}
put it in viewWillAppear: or viewDidAppear: which will be called each time the view is shown up (eg. you go back from the detail view to your search view). And reloading the data in this place would be nice too, to get the right data (for example if you marked the cell as read like in your sample code)
Just [self.tableView reloadData]; and not the searchResultsTableView (it will be automatically use the updated data after the new search)
It sounds as if perhaps your cells are being recycled and not reset properly. UITableView uses view recycling, so it's important that if you do something such as set an image you make sure it is explicitly set even when their isn't an image to display.
If you share your cellsForRowAtIndexPath code you might be able to get some more help.

NSUserDefaults not saving

I'm trying to save some data and call it back in a tableview from a different controller but it doesn't working. I'm somehow losing a variable value as well, like the category var changes back to zero when I change it in a view controller, any of them.
In my NewEntry.m I have:
-(IBAction)saveButton:(id)sender {
int i = selectedSegment.selectedSegmentIndex;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:i forKey:#"category"];
[userDefaults synchronize];
if (selectedSegment.selectedSegmentIndex == 0) {
[userDefaults setObject:titlefield.text forKey:#"titletexthomework"];
[userDefaults setObject:detailstextfield.text forKey:#"detailshomework"];
}
else if(selectedSegment.selectedSegmentIndex == 1) {
[userDefaults setObject:titlefield.text forKey:#"titletextprojects"];
[userDefaults setObject:detailstextfield.text forKey:#"detailsprojects"];
}
else if (selectedSegment.selectedSegmentIndex == 2){
[userDefaults setObject:titlefield.text forKey:#"titletextappointments"];
[userDefaults setObject:detailstextfield.text forKey:#"detailsappointments"];
}
else if (selectedSegment.selectedSegmentIndex == 3){
[userDefaults setObject:titlefield.text forKey:#"titletextevents"];
[userDefaults setObject:detailstextfield.text forKey:#"detailsevents"];
}
else if (selectedSegment.selectedSegmentIndex == 4){
[userDefaults setObject:titlefield.text forKey:#"titletexttodolist"];
[userDefaults setObject:detailstextfield.text forKey:#"detailstodolist"];
}
[userDefaults synchronize];
NSLog(#"selected segment %i", i);
}
then in my Projects.m I have:
-(void)viewDidLoad
{
[super viewDidLoad];
categoryselected = [[NSUserDefaults standardUserDefaults] integerForKey:#"category"];
NSLog(#"category selected %i", categoryselected);
titlestring = [[NSUserDefaults standardUserDefaults] objectForKey:#"titletextprojects"];
detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:#"detailsprojects"];
tabledata = [[NSArray alloc] initWithObjects:titlestring, nil];
tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil];
}
//-------------------------------------------------------
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"projectscell"];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"projectscell"];
}
cell.textLabel.text = [tabledata objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [tablesubtitles objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:14.0];
cell.textLabel.backgroundColor = [ UIColor clearColor ];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
return cell;
}
*******UPDATE**************
I Changed the part that populates the table to static string like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
tabl = [[NSArray alloc] initWithObjects:#"hello", nil];
NSLog(#"tabledata %#", tabledata );
tab = [[NSArray alloc] initWithObjects:#"hello2", nil];
NSLog(#"details %#", tablesubtitles);
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"projectscell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"projectscell"];
}
cell.textLabel.text = [tabl objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [tab objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:14.0];
cell.textLabel.backgroundColor = [ UIColor clearColor ];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
And the table still shows up blank.
Thanks For the help.
Call synchronize AFTER setting any values.
I don't notice anything wrong in the NSUserDefaults code, per se, though it's only grabbing the values when the view loads, not when the values are updated. To fix that, you could send a notification to let all other interested view controllers aware of the state change. In -[NewEntry saveButton:], after saving the values in NSUserDefaults, add
[[NSNotificationCenter defaultCenter] postNotificationName:#"ValuesChanged"
object:self];
to send a notification. Somewhere in Projects.m (init is a good place), subscribe to the notification with
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(valuesChanged:)
name:#"ValuesChanged"
object:nil];
This causes the notification center to call back to your valuesChanged: method when the notification is posted. We'll be updating the UI in pretty much the same way we did in viewDidLoad, so let's factor that code out:
- (void)reloadData
{
categoryselected = [[NSUserDefaults standardUserDefaults] integerForKey:#"category"];
NSLog(#"category selected %i", categoryselected);
// XXX - note the following strings are returned autoreleased. If they're
// stored in ivars, it's a good idea to retain them, even though we know
// they're retained by the arrays below.
titlestring = [[NSUserDefaults standardUserDefaults] objectForKey:#"titletextprojects"];
detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:#"detailsprojects"];
[tabledata release];
tabledata = [[NSArray alloc] initWithObjects:titlestring, nil];
[tablesubtitles release];
tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil];
[tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self reloadData];
}
- (void)valuesChanged:(NSNotification*)notification
{
[self reloadData];
}
One last thing: all those strings, the keys for NSUserDefaults and the notification name #"ValuesChanged"? They really should be defined as constants so that there's only one "true" version of the string. First, this saves you from the case where you accidentally misspell it in one place and wonder why the values aren't syncing up. It can take hours to figure out what's going on when that happens. (Speaking from experience here.) Second, the compiler can then check that you have the right name and the IDE's autocomplete (when it actually works) can suggest key names for you. You can do a #define in a shared header somewhere
#define kDefaultsKeySelectedCategory #"category"
and the linker will probably create a single constant instance of the string shared between every place it's used. Still, if I change the string in that define and Xcode's being cranky and doesn't recompile every source file that uses it, we're back to the case where the key is spelled differently in different places. No good. A fancier way to do this that ensures there's only one copy of the string is to declare
extern NSString* const kDefaultsKeySelectedCategory;
in the header file, then
NSString* const kDefaultsKeySelectedCategory = #"category";
in the .m file. Another thing I like about this way is it hides the implementation details. Nobody needs to know what the specific string is, so it shouldn't be in the header file.
I had the same issue when I was testing my app where if I use Stop in the debugger and then relaunch my app, the NSUserDefaults were incorrectly showing old list. This did not happen with the Insert operation, but with the Delete.
If I use the home button to exit the app (kill it), then relaunch, my NSUserDefaults were correct.
Alec Feb 23 '12 at 17:13 also mentioned this in an earlier comment.
I had an issue with NSUserDefaults not setting, even if you use the synchronize command right after. My issue was because the app was renamed and I believe that the NSUserDefaults didn't synchronize location correctly. I've uninstalled the app and reinstalled it from Xcode and it worked. I guess its a bit of a special case, but if anything try that.

iOS Refresh button in View Controller Nav: reloading all tableViewCells created from parsed JSON when clicked

I've got a fairly important conceptual issue that many people have asked about, but there isn't a readily available clear answer to be found by searching.
My application is simple: Several rows of TableViewCells populated with data from a parsed JSON feed. When a cell is clicked on, that cell's info is passed to a SecondViewController and displayed. The JSON feed is also stored to a .plist and in the case that the internet is not available, the TableViewCells are populated from the .plist.
This is all working great.
However, the last thing I need is a refresh button at the top of my FirstViewController to refresh the JSON feed, and all of the cells in the table with the new data from the new variables. However, I've encountered an issue with implementing this:
My original JSON call, and variables to populate the cells are located in the ViewDidLoad method. When the view loads, these variables are "set" and don't refresh. Further, I can move the JSON call and variables into viewWillLoad - which will refresh the table each time after clicking on a cell, and then clicking "back" to the firstViewController -- this will update the JSON and cells successfully, however it does impact the speed and makes the view controller "pause" when going back to the MainViewController, which makes calling my original JSON and setting my variables in viewWillLoad an unviable option.
I have created a reload button in ViewDidLoad, which is linked to an IBAction method "refresh":
Create Button Programitically in ViewDidLoad:
// Reload issues button
UIBarButtonItem *button = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(refresh:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
Action Method it's linked to:
- (IBAction)refresh:(id)sender {
myRawJson = [[NSString alloc] initWithContentsOfURL:[NSURL
URLWithString:#"http://www.yoursite.com/json.JSON"]
encoding:NSUTF8StringEncoding
error:nil];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary * myParsedJson = [parser objectWithString:myRawJson error:NULL];
// New updated dictionary built from refreshed JSON
allLetterContents = [myParsedJson objectForKey:#"nodes"];
// Log the new refreshed JSON
NSLog(#"You clicked refresh. Your new JSON is %#", myRawJson);
//Maybe use the notification center?? But don't know how to implement.
//[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshView:)
name:#"refreshView" object:nil];
//[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshView"
object:nil];
}
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows]
withRowAnimation:UITableViewRowAnimationNone];
[myRawJson release];
}
In the code above you can see that I'm re-calling the JSON each time the button is clicked and logging a message to console with the new JSON. This is working. I've even re-built a dictionary which is successfully adding the new content.
My question is: How can I make the tableViewCells "refresh" with this new data as well? Can I just make the button re-load the entire view controller - so it would call ViewDidLoad again? Do I need to re-think my apps structure, or move my original variables out of viewDidLoad?
I've been reading some posts on the NSNotificationCenter, but the implementation of this still baffles me, as I'm fairly new to iOS development.
Thanks~
Update:
It's still not updating. Here is my full refresh button code with [self.tableView reloadData]; called at the end of my IBAction.
- (IBAction)refresh:(id)sender {
[DSBezelActivityView newActivityViewForView:
self.navigationController.navigationBar.superview
withLabel:#"Loading Feed..." width:160];
myRawJson = [[NSString alloc] initWithContentsOfURL:[NSURL
URLWithString:#"http://site.com/mobile.JSON"]
encoding:NSUTF8StringEncoding
error:nil];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary * myParsedJson = [parser objectWithString:myRawJson error:NULL];
allLetterContents = [myParsedJson objectForKey:#"nodes"];
BOOL isEmpty = ([myParsedJson count] == 0);
if (isEmpty) {
NSString *refreshErrorMessage = [NSString
stringWithFormat:#"An internet or network connection is required."];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Alert"
message: refreshErrorMessage
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:nil];
[alert show];
[alert release];
allLetterContents = [NSMutableDictionary
dictionaryWithContentsOfFile:[self saveFilePath]];
//NSLog(#"allLetterContents from file: %#", allLetterContents);
} else {
NSLog(#"Your new allLetterContents is %#", allLetterContents);
// Fast enumeration through the allLetterContents NSMutableDictionary
for (NSMutableDictionary * key in allLetterContents) {
NSDictionary *node = [key objectForKey:#"node"];
NSMutableString *contentTitle = [node objectForKey:#"title"];
NSMutableString *contentNid = [node objectForKey:#"nid"];
NSMutableString *contentBody = [node objectForKey:#"body"];
// Add each Title and Nid to specific arrays
//[self.contentTitleArray addObject:contentTitle];
[self.contentTitleArray addObject:[[contentTitle
stringByReplacingOccurrencesOfString:#"&"
withString:#"&"] mutableCopy]];
[self.contentNidArray addObject:contentNid];
[self.contentBodyArray addObject:contentBody];
}
}
[self.tableView reloadData];
[DSBezelActivityView removeViewAnimated:YES];
[myRawJson release];
}
I'm configuring the cell at cellForRowAtIndexPath (Updated: Posted entire method):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
}
// Configure the cell.
cell.textLabel.text = [self.contentTitleArray objectAtIndex: [indexPath row]];
cell.detailTextLabel.text = [self.contentNidArray objectAtIndex: [indexPath row]];
return cell;
}
Setting it on didSelectRowAtIndexPath:
self.detailViewController.currentNodeTitle = [contentTitleArray
objectAtIndex:indexPath.row];
self.detailViewController.currentNodeNid= [contentNidArray
objectAtIndex:indexPath.row];
self.detailViewController.currentNodeBody = [contentBodyArray
objectAtIndex:indexPath.row];
So when clicking my refresh button the table should* refresh with the new json, but does not.. Am I missing a step?
Additionally this may not be important, but I'm changing the colors for every other row with:
// Customize the appearance of table view cells.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 2)
{
[cell setBackgroundColor:[UIColor colorWithRed:221.0/255.0 green:238.0/255.0 blue:255.0/255.0 alpha:1]];
cell.textLabel.textColor = [UIColor colorWithRed:2.0/255.0 green:41.0/255.0 blue:117.0/255.0 alpha:1];
cell.detailTextLabel.textColor = [UIColor colorWithRed:2.0/255.0 green:41.0/255.0 blue:117.0/255.0 alpha:1];
} else [cell setBackgroundColor:[UIColor clearColor]];
}
Update
You need to call the reload method.
[self.tableView reloadData];
This will fire the dataSource and delegate events an will refresh the UITableView.
You can find more info in the UITableView Class Reference:
Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible.

dequeueReusableCellWithIdentifier causing problem on UIImageView

I am loading a tableView with 500 rows. The problem is that in each row there is a different picture. Or when I use dequeueReusableCellWithIdentifier, those picture are just loaded again and the real pictures I am looking for are not shown (I just have about 8 different pictures : the first 8 loaded on my screen). If I don't use the dequeureReusableCellIdentifier, all the picture are loaded. But will it slow the displaying ?
Here is the code (I am currently working on getting the picture cached) :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomCellIdentifier = #"CustomCellIdentifier";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier: CustomCellIdentifier];
NSLog(#"Launching CellForRowAtIndexPath");
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell"
owner:self options:nil];
if ([nib count] > 0) {
cell = self.profilCell;
} else {
NSLog(#"failed to load CustomCell nib file!");
}
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [listProfils objectAtIndex:row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:nameValueTag];
nameLabel.text = [rowData objectForKey:#"name"];
NSString *finalId = [NSString stringWithFormat:#"http://graph.facebook.com/%#/picture", [rowData objectForKey:#"id"]];
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:finalId]]];
[profilPic setImage:image];
return cell;
}
THank you ! :)
It looks like you have an ivar profilPic that is probably an outlet that gets linked when you load a new cell nib. If that's the case, it's always going to point to the last cell that you loaded and won't change the image in the cell you've just dequeued. Instead of using an outlet, you might want to identify that custom view some other way, like a tag. So, if you set the profile pic UIImageView's tag to 100, for example, in Interface Builder, you could do something like this:
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:finalId]]];
UIImageView* cellImageView = (UIImageView*)[cell viewWithTag:100];
[cellImageView setImage:image];
Also, I just want to point out that -dataWithContentsOfURL: will load the URL synchronously on the main thread. If you're testing in the simulator on a fast connection, this will work pretty well. If, however, you are on 3G in SoHo on Friday afternoon... your app will probably start being killed by the watchdog.
I just met this problem, my solution is hold a private NSMutableDictionary to store the new images which asynchronously loaded from web before, use my identifier as key, UIImageView as Object (because I need to load the icon image first), when web image is ready, change it, When tableView dequeue return's null, I can read the original UIImage from my own cache.
Something like this.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
UIImageView *imageView = [thumbnailCache objectForKey:identifier];
if (!imageView) {
cell.imageView.image = [UIImage imageNamed:#"icon.png"];
[thumbnailCache setObject:cell.imageView forKey:identifier];
} else {
cell.imageView.image = imageView.image;
}
}
When I load the actual image from web, refresh the thumbnail cache.
asynchronously_load_image_from_web(^(UIImage *image) {
cell.imageView.image = image;
[thumbnailCache setObject:cell.imageView forKey:identifier];
});

2 NSArrays in one UITableView with Label as subView?

I'm having a problem with my current App. It has one UITableView in the UIViewController. I have one UIButton at the bottom (out of the UITableView). It works in that way:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"bla"]) {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:#"bla"];
[tableView reloadData];
} else {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"tasks2do"];
[tableView reloadData]; }
This worked when I had the cell.textLabel.text Method in this way:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ident = #"indet";
cell = [tableView dequeueReusableCellWithIdentifier:ident];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease];
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"bla"]) {
cell.textLabel.text = [firstArray objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [secondArray objectAtIndex:indexPath.row];
}
return cell; }
Now I want to use an UILabel instead of cell.textLabel, because I need it for some reasons (eg. setting the labels frame)
For that I used the following code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ident = #"indet";
cell = [tableView dequeueReusableCellWithIdentifier:ident];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease];
}
UILabel *thislabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 44)] autorelease];
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"bla"]) {
[thislabel setText:[firstArray objectAtIndex:indexPath.row]];
} else {
[thislabel setText:[secondArray objectAtIndex:indexPath.row]];
}
[cell.contentView addSubview:thislabel];
return cell; }
That works fine, until I push the UIButton for switching. It switches, the cell shows the new text but behind the new text is still the old text as you can see here:
http://d.pr/Rqx2
(the firstArray contains the letter L, the secondArray contains the Letter J, it mixes up both up)
Do you have any idea for solving this problem since I tried some stuff (for example using 2 UILabels for the arrays and hide one)? Would be cool. :)
I hope my English is not too bad to understand, my English skills for writing aren't the best, I'm sorry for that.
If you need further information / code just post it, shouldn't be a problem.
I recommend you create a UITableViewCell subclass in which you configure the label (set frame and add it as subview in UITableViewCell's initializer). Add a property for setting the text in the label and write a setter like this for the property:
- (void)setLabelText:(NSString *)newLabelText
{
if ([self.labelText isEqualToString:newLabelText]) return;
[labelText autorelease];
labelText = [newLabelText copy];
self.label.text = labelText;
[self.label setNeedsDisplay]; // or perhaps [self setNeedsDisplay];
}
Edit: by the way, the issue you're dealing with is the caching. You recreate a new label every time a cell comes in view, even if the cell already had a label before. This happens because you initialize an UILabel outside the UITableViewCell initializer (which only should be called once for every cached cell, afterwards it can be retrieved from cache, including all it's subviews).