I'm getting an image from the AppDelegate, then setting it to the ViewController's table.imageView property. It's throwing me an NSRangeException:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (2) beyond bounds (2)'
I made sure my array and rows are counted by [array count]. Very confused. Here's the code:
#pragma mark - viewWillAppear
- (void)viewWillAppear:(BOOL)animated {
PBAppDelegate *dataObject = (PBAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *titleRead = dataObject.title;
NSString *descRead = dataObject.desc;
UIImage *imageRead = dataObject.image;
if ([titleRead isEqualToString:#"" ] || [descRead isEqualToString:#""]) {
// it's nil
} else {
if (titleRead) {
[data addObject:[NSArray arrayWithObjects:titleRead, descRead, imageRead, nil]];
dataObject.title = #"";
dataObject.desc = #"";
[tableView reloadData];
}
NSUserDefaults *dataDefaults = [NSUserDefaults standardUserDefaults];
[dataDefaults setObject:[NSArray arrayWithArray:data] forKey:#"dataArrayKey"];
[dataDefaults synchronize];
}
}
#pragma mark - viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
data = [[NSMutableArray alloc] init];
self.data = [[NSUserDefaults standardUserDefaults] objectForKey:#"dataArrayKey"];
[tableView reloadData];
}
#pragma mark - Table Datasource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [[data objectAtIndex:indexPath.row] objectAtIndex:0];
cell.detailTextLabel.text = [[data objectAtIndex:indexPath.row] objectAtIndex:1];
cell.imageView.image = [UIImage imageNamed:[[data objectAtIndex:indexPath.row] objectAtIndex:2]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
It's probably this line:
cell.imageView.image = [UIImage imageNamed:[[data objectAtIndex:indexPath.row] objectAtIndex:2]];
The console output says there are 2 elements in the array. Elements start at 0; so you can access objectAtIndex:0 and objectAtIndex:1. Two would be the 3rd element of the array, and is out of bounds.
Sorry if that's all obvious, just taking a quick stab... Enjoy. :)
EDIT
Actually, the issue could be that imageRead is nil when you add it to the array. That would cause the array to have only 2 elements in it. You may check for that, and/or use [NSNull null] if you don't have an image...
Make sure the array actually has 3 elements by doing something like this:
NSArray *array = [data objectAtIndex:indexPath.row];
if ([array count] > 2)
{
cell.imageView.image = [UIImage imageNamed:[array objectAtIndex:2]];
}
Related
I have textview in VC. Saving this textview using nsuserdefaults and get it later. In VC1 im getting saved textview and displaying in UITableView. But when i launch the app it automcatically displays "null" text in index 0.
VC:
-(void)save:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:textView.text forKey:#"savetext"];
[userData1 synchronize];
}
VC1:
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// textArray=[[NSMutableArray alloc]init];
txt=[[UITextView alloc]initWithFrame:CGRectMake(0, 0, 320, 400)];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *savedValue = [prefs stringForKey:#"savetext"];
NSLog(#"saved is %#",savedValue);
txt.text = [NSString stringWithFormat:#"%#", savedValue];
NSLog(#"text.txt is %#", txt.text);
MyAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if(![MyAppDelegate.textArray containsObject:txt.text]){
[MyAppDelegate.textArray addObject:txt.text];
}
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:MyAppDelegate.textArray forKey:#"save"];
[userData1 synchronize];
}
UITableView displays the text values using array:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"array is %#",myMutableArrayAgain);
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"mycell is %#",myMutableArrayAgain);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
NSLog(#"cell inside is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
This is all because the code is wrong at some places:
1) Nsmutable array with array is wrong:- as the userdefaults is returning you a single string.
So do it like this:-
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithObject:[userData1 valueForKey:#"savetext"]];
2) In VC you are saving the value for key in "savetext" but in VC1 you are retrieving the value as "save", so change it, it has been done in the above code.
// The above 2 points would solve your problem but I would say don't code like this as it would consume more memory and would remove tidyness of your code. The code which you have done can be done in a very efficient way.
I tell you .
// Take first View controller VC and add IBAction to a button and a textView or textField what ever.
Write this code in VC :-
.h file
#interface demoViewController : UIViewController{
IBOutlet UITextField *txt1;
}
-(IBAction)getData:(id)sender;
.m file
// first include header file of the next controller where you want to redirect suppose XYZ
#import XYZ.h
-(IBAction)getData:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:txt1.text forKey:#"savetext"];
demoViewController1 *demo=[[demoViewController1 alloc]initWithNibName:#"demoViewController1" bundle:nil];
[self.navigationController pushViewController:demo animated:NO];
}
// Take the second controller IN taht on ViewDisLoad or ViewDidAppear whatever you feel like
// Take a global MuttableArray
NSMutableArray *myMutableArrayAgain;
// I write this code on ViewDidload allocate the array here as MutableObject need to be allocated
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
myMutableArrayAgain=[[NSMutableArray alloc]init];
[myMutableArrayAgain addObject: [userData1 valueForKey:#"savetext"]];
// Now table View Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
NSLog(#"cell inside is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
// Apply this way you can do the stuff in less code and in a great way.
I have a uitableview that's displaying multiple selections with a custom checkmark. When selected the rows value is save using NSUserDefaults. The problem is that despite the values being saved the checkmarks disappear from the table cell rows. I can't figure out why.
thanks for any help, I'm really stuck on this.
Here's the .h code:
#interface CategoriesViewController : UITableViewController {
NSString *selectedCategoryTableString;
NSString *jsonStringCategory;
int prev;
}
// arForTable array will hold the JSON results from the api
#property (nonatomic, retain) NSArray *arForTable;
#property (nonatomic, retain) NSMutableArray *arForIPs;
#property (nonatomic, retain) NSMutableArray *categorySelected;
#property (nonatomic, retain) NSString *jsonStringCategory;
#property(nonatomic, retain) UIView *accessoryView;
#end
and the .m code:
#implementation CategoriesViewController
#synthesize jsonStringCategory;
#synthesize arForTable = _arForTable;
#synthesize arForIPs = _arForIPs;
- (void)viewDidLoad
{
[super viewDidLoad];
self.arForIPs=[NSMutableArray array];
self.categorySelected = [[NSMutableArray alloc] init];
[self reloadMain];
self.tableView.allowsMultipleSelection = YES;
}
-(void) reloadMain {
jsonString = #"http:///******";
// Download the JSON
NSString *jsonString = [NSString
stringWithContentsOfURL:[NSURL URLWithString:jsonString]
encoding:NSStringEncodingConversionAllowLossy|NSUTF8StringEncoding
error:nil];
NSMutableArray *itemsTMP = [[NSMutableArray alloc] init];
// Create parser
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *results = [parser objectWithString:jsonString error:nil];
itemsTMP = [results objectForKey:#"results"];
self.arForTable = [itemsTMP copy];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.arForTable 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.textLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
[cell.detailTextLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
cell.accessoryView.hidden = NO;
}
UIImageView *cellAccessoryImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon-tick.png"]] ;
UIImageView *cellAccessoryNoneImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#""]] ;
if([self.arForIPs containsObject:indexPath]){
cell.accessoryView = cellAccessoryImageView;
} else {
cell.accessoryView = cellAccessoryNoneImageView;
}
// Get item from tableData
NSDictionary *item = (NSDictionary *)[_arForTable objectAtIndex:indexPath.row];
// encoding fix
NSString *utf8StringTitle = [item objectForKey:#"name"];
NSString *correctStringTitle = [NSString stringWithCString:[utf8StringTitle cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding];
cell.textLabel.text = [correctStringTitle capitalizedString];
NSNumber *num = [item objectForKey:#"id"];
cell.detailTextLabel.text = [num stringValue];
cell.detailTextLabel.hidden = YES;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if([self.arForIPs containsObject:indexPath]){
[self.arForIPs removeObject:indexPath];
[self.categorySelected removeObject:[[self.arForTable objectAtIndex:indexPath.row] objectForKey:#"id"]];
} else {
[self.arForIPs addObject:indexPath];
[self.categorySelected addObject:[[self.arForTable objectAtIndex:indexPath.row] objectForKey:#"id"]];
NSLog(#"%# categorySelected",self.categorySelected);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"%# defaults categorySelected",[defaults arrayForKey:#"selectedCategoryTableString"]);
NSString *string = [self.categorySelected componentsJoinedByString:#","];
[defaults setObject:string forKey:#"selectedCategoryTableString"];
NSLog(#"%# STRING",string);
}
[tableView reloadData];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:NO];
[self.navigationController setNavigationBarHidden:YES animated:NO];
self.navigationController.toolbarHidden = YES;
}
First of all your code has lots of memory leaks, please do use the static analyzer and/or instruments to fix them, few for them are pretty obvious like you initialized the SBJSON parser and did not release it, itemsTMP is another.
I have rewritten your code to be much more efficient and memory friendly:
#interface CategoriesViewController : UITableViewController
{
NSArray *_items;
NSMutableArray *_selectedItems;
UIImageView *cellAccessoryImageView;
}
#end
#implementation CategoriesViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_selectedItems = [NSMutableArray new];
cellAccessoryImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon-tick.png"]] ;
[self reloadMain];
self.tableView.allowsMultipleSelection = YES;
}
- (void)reloadMain
{
NSString *jsonString = #"http:///******";
// Download the JSON
jsonString = [NSString
stringWithContentsOfURL:[NSURL URLWithString:jsonString]
encoding:NSStringEncodingConversionAllowLossy|NSUTF8StringEncoding
error:nil];
// Create parser
SBJSON *parser = [SBJSON new];
NSDictionary *results = [parser objectWithString:jsonString error:nil];
if (_items) [_items release];
_items = [[results objectForKey:#"results"] copy];
[parser release];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_items 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] autorelease];
[cell.textLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
[cell.detailTextLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
cell.accessoryView.hidden = NO;
}
NSDictionary *item = [_items objectAtIndex:indexPath.row];
if ([_selectedItems containsObject:item])
{
// preloaded image will help you have smoother scrolling
cell.accessoryView = cellAccessoryImageView;
}
else
{
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Get item from tableData
cell.textLabel.text = [[NSString stringWithCString:[[item objectForKey:#"name"] cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding] capitalizedString];
cell.detailTextLabel.text = [[item objectForKey:#"id"] stringValue];
cell.detailTextLabel.hidden = YES;
item = nil;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *item = [_items objectAtIndex:indexPath.row];
if ([_selectedItems containsObject:item])
{
[_selectedItems removeObject:item];
}
else
{
[_selectedItems addObject:item];
}
item = nil;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (void)dealloc
{
[_selectedItems release];
[cellAccessoryImageView release];
[super dealloc];
}
#end
Since in your table there is only one section. Try this approach and this will help you certainly.
In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath write following code;
if([self.arForIPs containsObject:[NSNumber numberWithInt:indexPath.row]]){
cell.accessoryView = cellAccessoryImageView;
} else {
cell.accessoryView = cellAccessoryNoneImageView;
}
And in - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath write code as below,
if([self.arForIPs containsObject:[NSNumber numberWithInt:indexPath.row]]){
[self.arForIPs removeObject:[NSNumber numberWithInt:indexPath.row]];
} else {
[self.arForIPs addObject:[NSNumber numberWithInt:indexPath.row]]
}
i was implementing the table view programmatically, where i set property of mSelectedSubUnitIndex of (NSIndexPath) type as non atomic and retain and synthesized in .m . When i load my tableviewcontroller then method:
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath
:(NSIndexPath *)indexPath
{
CGFloat height = 0.0;
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise allObjects]];
NSLog(#"mSelectedSubUnitIndex.row........%d",mSelectedSubUnitIndex.row);
NSLog(#"subUnitExercises........%d",[subUnitExercises count]);
if (indexPath.row == mSelectedSubUnitIndex.row && [subUnitExercises count]>1) {
height =CELL_EXPAND_HEIGHT ;
}
else {
height = CELL_NORMAL_HEIGHT;
}
return height;
}
run quite fine. When i return back to my tableviewcontoller from other controller then it crashes(object message send) at same method on line number 5 at NSLog, and give exception at method at [self.tableView reloadData];. It is resolved by commenting[self.tableView reloadData];.
-(void)viewDidAppear:(BOOL)animated
{
DebugLog(#"start");
//[self.tableview reloadData];
execountarray=[[NSMutableArray alloc]init];
for(int k=0;k<[mSubUnitsArray count];k++)
{
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:k];
NSArray *subUnitExercises = [subUnit.subUnitExercise allObjects];
[execountarray addObject:[NSString stringWithFormat:#"%d",[subUnitExercises
count]]];
}
///////////////
if (managedObjectContext){
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"TSubUnitExerciseProgress" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Order the events by creation date, most recent first.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"editDate" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,
nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext
executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
myNotes = nil;
[myNotes removeAllObjects];
}
else
{
[myNotes setArray: mutableFetchResults];
}
//NSLog(#"My notes count:--------unitviewcontroller--------------->%d",
[myNotes count]);
if([myNotes count] ==0)
{
setExer1Done:NO;
setExer2Done:NO;
}
else
{
NSLog(#"hey :P");
}
}
// [self.tableview reloadData];
}
didSelectRowAtIndex
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
DebugLog(#" -start- \n");
mSelectedSubUnitIndex = indexPath;
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise allObjects]];
if([subUnitExercises count]!=1)
{
NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:
[mSelectedSubUnitIndex row] inSection:0]];
[tableview beginUpdates];
[tableview deleteRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationFade];
[tableview insertRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationFade];
[tableview endUpdates];
}
else
{
//SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:
[mSelectedSubUnitIndex row]];
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise
allObjects]];
if ([subUnitExercises count] > 0) {
SubUnitExercise *subUnitExercise = [subUnitExercises
objectAtIndex:0];
[self loadSubUnitExercise:subUnitExercise];
}
}
}
this is running on iOS 4 but when i build through Xcode version 4.2 and iOS 5 (released oct-12, 2011) then it crashes. Can't figure out the problem. help me out!!
cellForRowAtIndex method
now i am getting exception at if-statement at mSelectedsubunitindex.row when i scroll, but i resolved only checking that if (indexPath.row){}, and also row remain selected when i return bad to my tableview controller
- (void)tableView:(UITableView *)tableView willDisplayCell:
(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
DebugLog(#"-start- \n");
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise allObjects]];
NSString *str1 = [[subUnit performSelector:#selector(title)]copy];
if ([str1 isEqualToString:#"1. was/were"])
{
global = str1;
}
//if(indexPath.row==mSelectedSubUnitIndex.row)
if(indexPath.row)
{
if ([subUnitExercises count] != 1)
{
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:
[mSelectedSubUnitIndex row]];
NSArray *subUnitExercises = [self sortArray:
[subUnit.subUnitExercise allObjects]];
SubUnitCell *subUnitcell = (SubUnitCell*) cell;
mCellSubTopicLabel.text = subUnit.title;
if([myNotes count] == 0)
{
NSNumber *isDone = [[subUnitExercises objectAtIndex:1] isDone];
[subUnitcell setExer2Done:NO];
mExer2Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
isDone = [[subUnitExercises objectAtIndex:0] isDone];
[subUnitcell setExer1Done:NO];
mExer1Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
}
else
{
NSNumber *isDone = [[subUnitExercises objectAtIndex:1] isDone];
[subUnitcell setExer2Done:[isDone boolValue]];
mExer2Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
isDone = [[subUnitExercises objectAtIndex:0] isDone];
[subUnitcell setExer1Done:[isDone boolValue]];
mExer1Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
}
[subUnitcell.contentView addSubview:mCellSubTopicContentView];
}
}
For some reason NSIndexPath assignment (=) and equality(==) is not working in IOS5. I have solved the problem using self before any NSIndexPath object e.g.
self.mSelectedSubUnitIndex
There is another way solving this assignment using copy like this:
anIndexPath = (NSIndexPath*) [anotherIndexPath copy];
Equality works in same way. Like:
if([self.mSelectedSubUnitIndex isEqual:anotherIndexPath])
{
}
Just had a quick once over of your code. Two things jump out at me:
1: The very last line of your tableView:cellForRowAtIndexPath: calls [self.tableview reloadData].
This is unnecessary as the returned cell will be displayed as you have just configured it. It would also seem that this would cause a drawing loop ("reloadData->cellForRowAtIndexPath->reloadData->cellForRowAtIndexPath-> etc..). Try removing this line and see if this fixes your problems.
2: You don't seem to be re-using cells although one of your comments seemt to imply that you think you are. I would expect the beginning of the method to start similar to the code below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
/* Load a custom cell from a NIB
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
*/
// Assume SubUnitCell exists somewhere
SubUnitCell *cell = [[[SubUnitCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Retrieve config data and configure the cell as required in the code below - real config code needs to be added
NSNumber *isDone = [NSNumber numberWithBool:NO];
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:[indexPath row]];
[cell setTitle:subUnit.title];
if([myNotes count] ==0)
{
[cell setExer1Done:NO];
[cell setExer2Done:NO];
}
else
{
NSLog(#"My notes count:--------unitviewcontroller----->%d",[myNotes count]);
}
// All your other configuration code
.......
.......
.......
return cell;
}
Also please try and post the symbolicated crash log so people can see the exact error and path to the error.
My app downloading posts from internet to UITableViewCell. When user taps on cell, i am need to set this article as read (like on Mail.app). I dont know how to do that.
I am adding url (when user press cell) to database (like "url|url|url"), open detail view. And when he goes back to UITableView checking existing url in DB. Table now is too slow!
Can u help me and say what other method i can use to do that? Like in mail.app. I am using custom cell and code in drawRect method. Please, help
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%d",indexPath.row];
NSMutableArray *array=[NSMutableArray array];
if([[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]!=nil)
[array addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]];
NSUInteger indexOfObject = [array count]>0?[array indexOfObject:[NSNumber numberWithInt:indexPath.row]]:100000; //I add this, because row don't want update using updateRowAtIndexPath
QuickCell *cell = (QuickCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil || (indexOfObject!=NSNotFound && indexOfObject!=100000))
{
cell = [[[QuickCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.frame = CGRectMake(0.0, 0.0, 320.0, 68.0);
cell.accessoryType = UITableViewCellAccessoryNone;
if([self.subject count]>0)
{
[self.allImages addObject:[NSNull null]];
NSString *userNameLJ = [NSString stringWithFormat:#"%#",[self.journalurl objectAtIndex:indexPath.row]];
userNameLJ = [userNameLJ stringByReplacingOccurrencesOfString:#"http://"
withString:#""];
userNameLJ = [userNameLJ stringByReplacingOccurrencesOfString:#".livejournal.com"
withString:#""];
userNameLJ = [userNameLJ stringByReplacingOccurrencesOfString:#"community/"
withString:#""];
NSString *postURL = [NSString stringWithFormat:#"http://m.livejournal.com/read/user/%#/%#",userNameLJ,[self.ditemid objectAtIndex:indexPath.row]];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[self.subject objectAtIndex:indexPath.row] forKey:#"title"];
[dict setObject:[Utilities replaceForCell:[Utilities flattenHTML:[self.entry objectAtIndex:indexPath.row]]] forKey:#"description"];
if([[database executeQuery:#"SELECT * FROM read WHERE posts=?;",postURL] count]>0)
{
//if this post is read
[dict setObject:[NSNumber numberWithBool:NO] forKey:#"highlighted"];
}
else {
[dict setObject:[NSNumber numberWithBool:YES] forKey:#"highlighted"];
}
[dict setObject:[self.journalname objectAtIndex:indexPath.row] forKey:#"nick"];
[cell setContentForCell:dict];
BOOL trueOrFalse = [[self.allImages objectAtIndex:indexPath.row] isKindOfClass:[NSNull class]]?YES:NO;
if(trueOrFalse)
{
if (tableView.dragging == NO && tableView.decelerating == NO)
{
//if no image cached now, download it
if(indexPath.row<6 && self.updating==YES)
[self startDownloading:indexPath];
if(self.updating==NO)
[self startDownloading:indexPath];
}
}
else
{
[cell setImageForCell:[self.allImages objectAtIndex:indexPath.row]];
}
}
if(indexOfObject!=NSNotFound && indexOfObject!=100000)
{
//delete this row from userdefaults
[array removeObjectAtIndex:indexOfObject];
if([array count]>0)
[[NSUserDefaults standardUserDefaults] setObject:array forKey:#"readPostS"];
else [[NSUserDefaults standardUserDefaults] removeObjectForKey:#"readPostS"];
}
}
return cell;
}
//////////////////////////////////////////////////////////////
///////-(void)viewWillApear
//////////////////////////////////////////////////////////////
NSMutableArray *readPosts = [NSMutableArray array];
if([[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]!=nil)
{
[readPosts addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]];
self.read = (NSMutableArray*)[database executeQuery:#"SELECT * FROM read;"];
for(int i=0;i<[readPosts count];i++)
{
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[[readPosts objectAtIndex:i] intValue] inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
}
///////////////////////////////////////////////
///////THIS FILE OPENS POSTS FOR READING
///////////////////////////////////////////////
if([[database executeQuery:#"SELECT * FROM read WHERE posts=?;",self.postURL] count]==0)
{
[database executeNonQuery:#"INSERT INTO read VALUES (?);",self.postURL];
NSMutableArray *defaults = [NSMutableArray array];
if([[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]!=nil)
defaults = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]];
[defaults addObject:[NSNumber numberWithInt:self.currentIndex]];
[[NSUserDefaults standardUserDefaults] setObject:defaults forKey:#"readPostS"];
}
Ok. I think, my code is to bad and u can understand, what i am doing here) Answer on other question. How i can update hidden cells? User see only 6 cell in a moment, i need to update, for example, 10 cells. How?
Or, how reload cell, if it allready exists? Lets say -
NSString *CellIdentifier = [NSString stringWithFormat:#"%d",indexPath.row];
QuickCell *cell = (QuickCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[QuickCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.frame = CGRectMake(0.0, 0.0, 320.0, 68.0);
cell.accessoryType = UITableViewCellAccessoryNone;
.........}
now cell exists and if i call reload data nothing happen. And reloadCellAtIndexPath does not working too, because cell has unique identifier and ixists.
HOW I CAN RELOAD CELL AND CALL DRAWRECT AGAIN?))
You can implement this functionality by adding your code in the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//Add the indexPath.row values in an array.
}
Add the custom functionality (like showing Title in BOLD for unread) in the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Check if the indexPath.row is available in the array
//If yes then Normalize the fonts
//Else Keep them BOLD.
}
Unless you're really doing some drawing, don't implement in drawRect:. I don't know you're specific code, so that may not be correct in your case.
To reload the entire table (all cells), look at UITableView's - (void)reloadData
To reload a specific cell, look at UITableView's - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation and use it to reload the cell in question.
I can't get my head round this. When the page loads, everything works fine - I can drill up and down, however 'stream' (in the position I have highlighted below) becomes not equal to anything when I pull up and down on the tableview. But the error is only sometimes. Normally it returns key/pairs.
If know one can understand above how to you test for // (int)[$VAR count]} key/value pairs
in a NSMutableDictionary object
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *FirstLevelCell = #"FirstLevelCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:FirstLevelCell];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstLevelCell] autorelease];
}
NSInteger row = [indexPath row];
//NSDictionary *stream = (NSDictionary *) [dataList objectAtIndex:row];
NSString *level = self.atLevel;
if([level isEqualToString:#"level2"])
{
NSMutableDictionary *stream = [[NSMutableArray alloc] init];
stream = (NSMutableDictionary *) [dataList objectAtIndex:row];
// stream value is (int)[$VAR count]} key/value pairs
if ([stream valueForKey:#"title"] )
{
cell.textLabel.text = [stream valueForKey:#"title"];
cell.textLabel.numberOfLines = 2;
cell.textLabel.font =[UIFont systemFontOfSize:10];
NSString *detailText = [stream valueForKey:#"created"];
cell.detailTextLabel.numberOfLines = 2;
cell.detailTextLabel.font= [UIFont systemFontOfSize:9];
cell.detailTextLabel.text = detailText;
NSString *str = #"http://www.mywebsite.co.uk/images/stories/Cimex.jpg";
NSData *imageURL = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:str]];
UIImage *newsImage = [[UIImage alloc] initWithData:imageURL];
cell.imageView.image = newsImage;
[stream release];
}
}
else
{
cell.textLabel.text = [dataList objectAtIndex:row];
}
return cell;
}
Thanks for your time
You are both leaking and over-releasing the stream dictionary:
NSMutableDictionary *stream = [[NSMutableArray alloc] init]; // <-- Create a new dictionary
stream = (NSMutableDictionary *) [dataList objectAtIndex:row]; // <-- Overwrite the reference with another dictionary. Previous dictionary is lost...
...
[stream release]; // <-- You are releasing an object you don't have the ownership.
You should remove the dictionary creation as it is useless and the release as you don't own the object.
I didn't really understand the question, but...
You can test for number of values in a dictionary by:
if ([[myDictionary allKeys] count] == someNumber) {
// do something...
}