I am getting a crash when i go back and forth in navigation controller where one has a tableview. I used instruments to see what is going on and i see that when i go back to the first view controller i get
[_NSCoreManagedObjectID allocateBatch:Count:] leaks. Here is the screenshot from Instruments
The more i go back and forth the more leaks come up. What would be the reason for this? I set nsfetchedresultcontroller to nil in viewdidunload, but i don't set it to nil when i go between tabs.
Thanks!
UPDATE:
I did some testing and i found that if i comment
Person *person = [self.fetchedResultsController objectAtIndexPath:indexPath];
in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"personCell";
PeopleListTableViewCell *cell = (PeopleListTableViewCell *) [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[PeopleListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
Person *person = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.personName.text = person.fullname;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM-dd-yyyy"];
NSDate *tmpDate = person.dateofbirth;
NSString *strDate = [dateFormatter stringFromDate:tmpDate];
cell.personDateOfBirth.text = strDate;
NSString *imgURL=[person.imageurl stringByAppendingString:#"?maxheight=120&maxwidth=156"];
[cell.personImage setImageWithURL:[NSURL URLWithString:imgURL] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
return cell;
}
The leak goes away. I am using this tableviewcontroller as a delegate to a tableview in a different uivewcontroller.
This is how i set it when the button is clicked to show this table
- (void)signPeople
{
self.signInfoView.hidden = YES;
self.pplTableView.hidden = NO;
self.hud = [[ATMHud alloc]initWithDelegate:self];
[self.hud setActivity:YES];
self.hud.shadowEnabled = YES;
[self.view addSubview:self.hud.view];
[self.hud show];
if(!self.pplListTableViewController){
self.pplListTableViewController = [[PeopleListTableViewController alloc]init];
}
self.pplListTableViewController.delegate = self;
self.pplTableView.delegate = self.pplListTableViewController;
self.pplTableView.dataSource = self.pplListTableViewController;
//shows the People List
[self.pplListTableViewController setupFetchResultsController];
[self.pplTableView reloadData];
[self.pplTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES]; //scroll to top
}
I tried to nil out the tableview here and there and also dealloc the labels and person class nothing helps. What could be keeping the people class from getting freed. thanks!
Related
Basically, every time I enter something in my textfield and save it to the table, the previous entry will be replaced by the new one. How do I add elements in a mutable array and save the last entry? I tried
[tabledata addObject....
and in the entry
tabledata.lastObject objectAtIndex...
but that didn't work.
here is what I have:
-(void)viewDidLoad
{
[super viewDidLoad];
titlestring = [[NSUserDefaults standardUserDefaults] objectForKey:#"titlehomework" ];
detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:#"detailshomework"];
tabledata = [[NSMutableArray alloc] initWithObjects:titlestring, nil];
tablesubtitles = [[NSMutableArray alloc] initWithObjects:detailsstring, nil];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return [tabledata count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"homeworkcell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"homeworkcell"];
}
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];
//-----------------------------------------START----------------------------Set image of cell----
cellImage = [UIImage imageNamed:#"checkboxblank.png"];
cell.imageView.image = cellImage;
//--------------------------------------------END---------------------------end set image of cell--
return cell;
}
Without seeing more code, the best I can do is suggest something like this
[tabledata addObject:newTitle];
[tablesubtitles addObject:newSubtitle];
[tableView reloadData];
This assumes both newTitle and newSubtitle are the NSStrings you wish to add and that tableView is the pointer to the UITableView.
I have a UIViewController with two UI Components: UITableView and UIDatePicker. My goal is, to create a screen like the ical->add->Start & End.
I added the the tableView delegate and dateSource to my header file. In the implementation file, I want to display the current value from the datePicker in my tableCell (like the iCal Start & End screen).
My .m looks like the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[datePicker addTarget:self action:#selector(datePickerValueChanged) forControlEvents:UIControlEventValueChanged];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSMutableArray *dict = [dictionary objectForKey:#"DATA"];
if(indexPath.row == 1){
UISwitch *switchSpecifyEnd = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
cell.accessoryView = switchSpecifyEnd;
[(UISwitch *)cell.accessoryView setOn:NO]; // Or NO, obviously!
[(UISwitch *)cell.accessoryView addTarget:self action:#selector(switchSpecifyEnd)
forControlEvents:UIControlEventValueChanged];
cell.textLabel.text = [dict objectAtIndex:indexPath.row];
}else if(indexPath.row == 3){
UISwitch *switchOpenEnd = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
cell.accessoryView = switchOpenEnd;
[(UISwitch *)cell.accessoryView setOn:NO]; // Or NO, obviously!
[(UISwitch *)cell.accessoryView addTarget:self action:#selector(switchOpenEnd)
forControlEvents:UIControlEventValueChanged];
cell.textLabel.text = [dict objectAtIndex:indexPath.row];
}else{
cell.textLabel.text = [dict objectAtIndex:indexPath.row];
// NSLog(#"Update Cell: %#",<but how>);
}
return cell;
}
- (void)datePickerValueChanged{
NSLog(#"Logging: %#", [NSString stringWithFormat:#"%#",datePicker.date]);
}
How can I update my tableCell with the value from the datePicker?
BR,
mybecks
For updating your table cell you need to reload your table and when your table will reload then cellForRowAtIndexPath will get call and you can update your cell text.
Suppose this is your method that gets called when you select some date in date picker
-(IBAction)setStartTimeMethod
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EEE MMM dd, yyyy hh:mm a"];
self.startTimeString = [dateFormat stringFromDate:[timeStartPicker date]];
[dateFormat release];
[optionsTableView reloadData];
}
I have a table list of promotions held in an NSSet which I load into an array for the purpose of displaying the title/name on the cell. However I want to use the didselectrow method to push the selected promotion onto an individual promotion page. I've making promo.featuredArray = self.featuredArray however it doesn't seem to be passing the data. My code is as follows.
Promo list.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
Featured*featured = [self.featuredArray objectAtIndex:indexPath.row];
cell.textLabel.text = featured.details;
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.text = self.place.name;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Promo * promo= [[Promo alloc] initWithNibName:#"Promo" bundle:nil];
//Featured*featured = [self.featuredArray objectAtIndex:indexPath.row];
promo.featuredArray = self.featuredArray;
[self.navigationController pushViewController:promo animated:YES];
[promo release];
//[featured release];
}
Promo.m
#synthesize featuredArray, featured = __featured;
- (void)viewDidLoad
{
self.clearImage = [UIImage imageNamed:#"fav_icon.png"];
self.clearImagePressed = [UIImage imageNamed:#"fav_icon_sel.png"];
Featured*featured = [self.featuredArray init];
self.name.text = [NSString stringWithFormat:#"%#", __featured.name];
self.time.text = [NSString stringWithFormat:#"%#", __featured.time];
// self.description.text = [NSString stringWithFormat:#"%#", __featured.description];
self.placeName.text = [NSString stringWithFormat:#"%#", __featured.Place];
[super viewDidLoad];
if([__featured.imageURL hasPrefix:#"http"])
{
[self getImageForPlace];
}
// else
// {
// [self refreshImage];
// }
//
self.title = #"Promotion";
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"background_texture.png"]];
self.view.backgroundColor = background;
[background release];
[featured release];
}
It's probably this line:
Featured*featured = [self.featuredArray init];
This is wrong in many ways.
Making this a community wiki because I don't have time to write a full answer.
Please help with this issue of using NSFetchedResultsController.
I created an object of NSFetchedResultsController and I use it once in the method: tableView:cellForRowAtIndexPath: and when I try to execute the same code in the method tableView:didSelectRowAtIndexPath: I get EXC_BAD_ACCESS.
Here is the code of the 2 methods
- (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];
}
Person *person = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = person.name; //This works fine
[person release];
return cell;
}
and here is the problematic snippet:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PhotoListViewController *photoListViewController = [[PhotoListViewController alloc] initWithNibName:#"PhotoListViewController" bundle:nil];
//The next line returns a bad object or undefined memory
Person *person = [fetchedResultsController objectAtIndexPath:indexPath];
//causing the call of [person name] to return EXC_BAD_ACCESS
photoListViewController.person = [person name];
[self.navigationController pushViewController:photoListViewController animated:YES];
[photoListViewController release];
[person release];
}
Please help me understand why the code is breaking there.
Appreciate any suggestions.
Person *person = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = person.name; //This works fine
[person release];
[person release] is the problem - no need to release person if it's not alloc'd there. That causes person to be over-released, leading to the crash when something else tries to access it.
Even though, in this example, it's ok to manipulate an autoreleased object (due to simplicity of the manipulations, i.e. you are just grabbing one property of *person), the proper way would be to retain your Person object and release it at the end:
Person *person = [[fetchedResultsController objectAtIndexPath:indexPath] retain];
// bla bla
[person release];
I am working for the first time in objective c and have come across an issue that I have not seen an answer for.
I am loading a set of data from a JSON data set and using it to populate a UITableView within a UITableViewController.
First when the view is loaded (viewDidLoad) I populate the array with the JSON data from a URL.
Next the data loads as it should. numberOfRowsInSection shows that there are 30 results in the array which is correct.
However The Iphone loads the entire set three times into the tableview.
Here is some code from the controller for that view:(Twitter is being used as an example and is not the actual data set I use)
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
//results = [[NSMutableArray alloc] init];
self.navigationItem.title=#"public_timeline";
self.tableView.allowsSelection = NO;
NSString *url = [[NSString alloc] init];
url = [[NSString alloc] initWithFormat:#"http://twitter.com/statuses/%s.json",#"public_timeline"];
if ([results count] == 0) {
[self parseJSON:url];
}
}
Here is the parseJSON (actual parse is done with the Cocoa JSON framework
-(void) parseJSON:(NSString *)URL{
NSURL *JSONURL = [NSURL URLWithString:URL];
NSData *responseData = [[NSData alloc] initWithContentsOfURL:JSONURL];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
results = [[NSMutableArray alloc] initWithArray:[responseString JSONValue]];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [results count];
}
then the cell's output
- (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];
// Set up the cell...
}
NSDictionary *cdict = [results objectAtIndex:indexPath.row];
cell.textLabel.text = [cdict valueForKey:#"text"];
return cell;
}
I am not sure if what I am doing is the best way to do this, so if someone could help me out that would be great.
Check the numberOfSectionsInTableView Method and change the return Value to 1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}