Uncheck (unfavorite) items in Favorites Table View - objective-c

I have a tableview that displays a list of "favorited" items. Users favorite items in another tableview, and favorited items are listed in this tableview (FavoritesTableView.m).
For some reason, I can't get checked items (favorited items) to "uncheck" from the FavoritesTableView? What am I missing?
See the .m file below...
FavoritesViewController.h
#import <UIKit/UIKit.h>
#import "StrainTableCell.h"
#interface FavoritesViewController : UITableViewController
{
}
#property (strong, nonatomic) NSArray *favoritesArrayset;
#property (strong, nonatomic) IBOutlet UITableView *favoritesTable;
#property (nonatomic, strong) NSMutableArray * favoritesArray;
- (IBAction)backbuttonpressed: (UIBarButtonItem *)sender;
#end
FavoritesViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
if (favoritesArray == Nil)
{
favoritesArray = [[NSMutableArray alloc] init];
}
else
{
[favoritesArray removeAllObjects];
}
NSData *dataSave = [[NSUserDefaults standardUserDefaults] objectForKey:#"strains"];
if (dataSave != Nil)
{
favoritesArrayset = [NSKeyedUnarchiver unarchiveObjectWithData:dataSave];
for (NSDictionary *item in favoritesArrayset)
{
BOOL isChecked = [[item objectForKey:#"checked"] boolValue];
if (isChecked == YES )
{
[favoritesArray addObject:item];
}
}
}
[favoritesTable reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return favoritesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *Strains = [favoritesArray copy];
NSArray *dataArray = [favoritesArray copy];
static NSString *strainTableIdentifier = #"StrainTableCell";
StrainTableCell *cell = (StrainTableCell *)[tableView dequeueReusableCellWithIdentifier:strainTableIdentifier];
if (cell == nil)
{
cell = [[StrainTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strainTableIdentifier] ;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StrainTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.titleLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Title"];
cell.descriptionLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Description"];
cell.ratingLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Rating"];
cell.ailmentLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Ailment"];
cell.actionLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Action"];
cell.ingestLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Ingestion"];
cell.whatCellamI = [NSNumber numberWithInt:indexPath.row];
NSMutableDictionary *item = [dataArray objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:#"text"];
[item setObject:cell forKey:#"StrainTableCell"];
}
BOOL checked = [[item objectForKey:#"checked"] boolValue];
UIImage *image = (checked) ? [UIImage imageNamed:#"checked.png"] : [UIImage imageNamed:#"unchecked.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
StrainDetailViewController *detailViewController = [[StrainDetailViewController alloc]
initWithNibName:#"StrainDetailViewController" bundle:nil];
detailViewController.title = [[favoritesArray objectAtIndex:indexPath.row] objectForKey:#"Title"];
detailViewController.strainDetail = [favoritesArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 82;
}
- (IBAction)backbuttonpressed:(id)sender
{
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)checkButtonTapped:(id)sender event:(id)event
{
NSLog(#"made it here and event is %#",event);
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.favoritesTable];
NSIndexPath * indexPath ;
indexPath = [self.favoritesTable indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"indexpath is below");
NSLog(#"%#",indexPath);
if (indexPath != Nil)
{
NSMutableDictionary *item = [favoritesArray objectAtIndex:indexPath.row];
BOOL isItChecked = [[item objectForKey:#"checked"] boolValue];
/*
if (isItChecked == NO) {
NSMutableArray *tmpArray = [[NSMutableArray alloc] init];
NSMutableArray *tmpArray2 = [[NSMutableArray alloc] initWithArray:[favoritesArray allObjects]];
NSString *text1 = [item objectForKey:#"Title"];
for (NSDictionary * object in tmpArray2) {
NSString *text2 = [object objectForKey:#"Title"];
if (![text1 isEqualToString:text2]) {
[tmpArray addObject:object];
}
}
// [favoritesArray removeAllObjects];
favoritesArray = [tmpArray copy];
}
*/
NSMutableArray *quickArray = [[NSMutableArray alloc] initWithArray:favoritesArray];
[quickArray replaceObjectAtIndex:indexPath.row withObject:item];
[item setObject:[NSNumber numberWithBool:!isItChecked] forKey:#"checked"];
favoritesArray = [quickArray copy];
// [self.favoritesArray addObject:item];
// NSLog(#"you have added %d items to favorites", self.favoritesArray.count);
[favoritesTable reloadData];
}
#end

In your .h take one NSMutableDictionary and do property to it.
In your .m synthesize it,and in viewdidLoad alloc the Dictionary.
Now put this below code in CellForRowAtIndex
if([idDictonary objectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
and put this below code in DidSelectRowAtIndex
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
[idDictonary setValue:[dataArray objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"%d",[indexPath row]]];
}
else
{
if([idDictonary objectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]])
{
[idDictonary removeObjectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]];
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
[myTableView reloadData];
NSLog(#"idDictonary = %#",idDictonary);
i hope this will helps u Brittany...

Every time -tableView:cellForRowAtIndexPath: runs, you create a new button, set it to the desired properties and … throw it away. (Seems to be the running joke this week.) You have to use the existing button.

Related

How to pass a Dictionary data from table View to the another View Controller

I am fetching the contacts of iPhone and make their Dictionary Check my code
-(void) fetchContacts
{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
UIImage *profileImage;
NSMutableArray *contactNumbersArray;
for (CNContact *contact in cnContacts) {
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:#"acc_sett.png "];
}
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,#"fullName",profileImage,#"userImage",phone,#"PhoneNumbers", nil];
[_Contacts addObject:personDict];
NSLog(#"%#",phone);
NSLog(#"%#",fullName);
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.contacttableview reloadData];
});
}
}
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_Contacts count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary* personDict = [_Contacts objectAtIndex:indexPath.row];
UITableViewCell *cell = nil;
cell = [_contacttableview dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.imageView.image = [personDict objectForKey:#"userImage"];
cell.textLabel.text = [personDict objectForKey:#"fullName"];
cell.detailTextLabel.text = [personDict objectForKey:#"phoneNumbers"];
return cell;
}
With the help of this code Dictionary Data is display on the tableview now i want to pass image fullname and phone number of a person on the another view controller on selecting their row.
I have tried many method but not get any result
In YourViewController.h, create a property of Person that you want to pass
#property (nonatomic, assign) NSDictionary *person;
In TableViewController.m, didSelectRowAtIndexPath:
YourViewController *vc = [[YourViewController alloc] init];
vc.person = [_Contacts objectAtIndex:indexPath.row];
[self.navigationController pushViewController:vc animated:YES];
First create any NSDictionary object or Your model class object on OtherViewController where you want to navigate then write code like Below,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
OtherViewController *VC = [[OtherViewController alloc] init];
VC.objContactModel = [_Contacts objectAtIndex:indexPath.row];
[self.navigationController pushViewController:VC animated:YES];
}
Hope it will work.

UITableView reloadData lose elements from cell

I have a UITableView and his datasource is an NSMutableArray declared in my interface:
#property (strong, nonatomic) NSMutableArray *arrElements;
Now I implemented a simple "load more" in this way:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
//only if i have others results i will call load more
if([self.items_amount integerValue] > self.arrElements.count) {
if(DEBUG_MODE == 1) {
NSLog(#"Load more");
}
//get start param from array size and call load more
NSNumber *start = [NSNumber numberWithInteger:([self.arrElements count]+1)];
NSArray *passParams = [NSArray arrayWithObjects:self.menuItem,start,[NSNumber numberWithInteger:NUM_RESULTS_FOR_PAGE], nil];
[self performSelector:#selector(loadMore:) withObject:passParams afterDelay:0.1];
}
}
}
and this is my loadMore method:
//load more elements
- (void)loadMore:(NSArray *)arrParams {
//(MenuItem *)menuItem startingFrom:(NSNumber *)start numResults:(NSNumber *)results;
MenuItem *menuItem = [arrParams objectAtIndex:0];
NSNumber *start = [arrParams objectAtIndex:1];
NSNumber *results = [arrParams objectAtIndex:2];
if(DEBUG_MODE == 1) {
NSLog(#"Before load more %lu", (unsigned long)[self.arrElements count]);
}
//call API and parse it
WebServicesClient *restClient = [[WebServicesClient alloc] init];
NSData *data = [restClient callWorkAPI:[menuItem pathAPI] inLanguage:[[NSLocale preferredLanguages] objectAtIndex:0] withLat:self.latitude withLng:self.longitude startingFrom:start numRows:results];
for(Work* work in [[restClient parseWorks:data] objectForKey:#"items"]) {
[self.arrElements addObject:work];
}
if(DEBUG_MODE == 1) {
NSLog(#"After load more %lu", (unsigned long)[self.arrElements count]);
}
[self.tableElem reloadData];
}
And this is my custom cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier;
CellIdentifier = #"HomeCell";
HomeCell *cell = (HomeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Work *work = (Work *)[[self arrElements] objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor clearColor];
cell.labelTitleItem.text = [work title];
cell.labelSubtitleItem.text = #"my category"
//if exists image
if([[work image] isKindOfClass:[NSString class]] && [[work image] length] > 0) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:[work image]]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageItem.image = [UIImage imageWithData: data];
});
});
} else {
//remove image setting height to 0
[cell.imageItem setFrame:CGRectMake(cell.imageItem.frame.origin.x, cell.imageItem.frame.origin.y, cell.imageItem.frame.size.width, 0)];
}
if([[work distance] isKindOfClass:[NSString class]]) {
[cell.imagePriority setBackgroundColor:[UIColor lightGrayColor]];
cell.labelDistanceItem.text = [self convertDistance:[work distance]];
cell.labelDistanceItem.textColor = [UIColor whiteColor];
} else {
//remove image setting height to 0
[cell.imagePriority setFrame:CGRectMake(cell.imagePriority.frame.origin.x, cell.imagePriority.frame.origin.y, cell.imagePriority.frame.size.width, 0)];
//remove label distance setting height to 0
[cell.labelSubtitleItem setFrame:CGRectMake(cell.labelSubtitleItem.frame.origin.x, cell.labelSubtitleItem.frame.origin.y, cell.labelSubtitleItem.frame.size.width, 0)];
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self arrElements] count];
}
Now the problem is that after reloadData i lose the text of a UILabel (my category) of my CustomCell
please, Any suggests?
I've had similar problems with TalbeViews. Try using the method
- (void) tableView:(UITableView *)tableView willDisplayCell:(RCGameTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
to add the elements that you want. Keep the cell initialization that you do at the beginning of cellForRowAtIndexPath, but then return the cell right after and set the background color, labels, images, etc. in the willDisplayCell delegate function I mentioned.

removeObjectAtIndex crashing the app

In the .h file I have set the below line.
NSMutableArray *repArray;
In the .m file I have placed the below lines.(I put just the required lines of code for this ex)
-(void)read_data_fromDB
{
objectsForCharacters = [[NSMutableDictionary alloc]init];
sqlite3 *db = [contactAppDelegate getNewDBConnection];
NSMutableString *query = nil;
query = [NSMutableString stringWithFormat:#"select representative, title, business_name, uid from corporate where profiler_type <> 'OWN_CORPORATE' order by representative asc"];
const char *sql = [query UTF8String];
sqlite3_stmt *selectAllStmt = nil;
if(sqlite3_prepare_v2(db,sql, -1, &selectAllStmt, NULL)!= SQLITE_OK)
NSAssert1(0,#"error preparing statement",sqlite3_errmsg(db));
else
{
repArray = [[NSMutableArray alloc]init];
businessArray = [[NSMutableArray alloc]init];
titleArray = [[NSMutableArray alloc]init];
uidArray = [[NSMutableArray alloc]init];
while(sqlite3_step(selectAllStmt)==SQLITE_ROW)
{
char *chrstr =(char *)sqlite3_column_text(selectAllStmt, 0);
if(chrstr !=NULL)
{
corpRepresentative = [NSString stringWithUTF8String:chrstr];
[repArray addObject:corpRepresentative];
}
chrstr =(char *)sqlite3_column_text(selectAllStmt, 1);
if(chrstr !=NULL)
{
corpTitle = [NSString stringWithUTF8String:chrstr];
[titleArray addObject:corpTitle];
}
chrstr =(char *)sqlite3_column_text(selectAllStmt, 2);
if(chrstr !=NULL)
{
corpBusiness_name = [NSString stringWithUTF8String:chrstr];
[businessArray addObject:corpBusiness_name];
}
chrstr =(char *)sqlite3_column_text(selectAllStmt, 3);
if(chrstr !=NULL)
{
corporteUid = [NSString stringWithUTF8String:chrstr];
[uidArray addObject:corporteUid];
}
}
}
sqlite3_finalize(selectAllStmt);
sqlite3_close(db);
}
- (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];
UILongPressGestureRecognizer *longPressGesture =
[[[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(longPress:)] autorelease];
[cell addGestureRecognizer:longPressGesture];
}
// Configure the cell...
UILabel *txtLbl = [[UILabel alloc]initWithFrame:CGRectMake(70, 0, 175, 26)];
//[txtLbl setBackgroundColor:[UIColor greenColor]];
[txtLbl setTextAlignment:UITextAlignmentLeft];
NSString *txtStr = [repArray objectAtIndex:indexPath.row];
UIFont *fontTxtLbl = [UIFont fontWithName: #"FuturaMdBT" size:16];
[txtLbl setFont:fontTxtLbl];
[txtLbl setText:txtStr];
[cell.contentView addSubview:txtLbl];
[txtLbl release];
UILabel *txtDetailLbl = [[UILabel alloc]initWithFrame:CGRectMake(70, 27, 175, 20)];
// [txtDetailLbl setBackgroundColor:[UIColor redColor]];
[txtDetailLbl setTextAlignment:UITextAlignmentLeft];
NSString *txtDetailStr = [titleArray objectAtIndex:indexPath.row];
UIFont *fontTxtDetailLbl = [UIFont fontWithName: #"Arial" size:12];
[txtDetailLbl setFont:fontTxtDetailLbl];
[txtDetailLbl setText:txtDetailStr];
[cell.contentView addSubview:txtDetailLbl];
[txtDetailLbl release];
UILabel *txtDetailLbl1 = [[UILabel alloc]initWithFrame:CGRectMake(70, 47, 175, 20)];
//[txtDetailLbl1 setBackgroundColor:[UIColor blueColor]];
[txtDetailLbl1 setTextAlignment:UITextAlignmentLeft];
NSString *txtDetailStr1 = [businessArray objectAtIndex:indexPath.row];
UIFont *fontTxtDetailLbl1 = [UIFont fontWithName: #"Arial" size:12];
[txtDetailLbl1 setFont:fontTxtDetailLbl1];
[txtDetailLbl1 setText:txtDetailStr1];
[cell.contentView addSubview:txtDetailLbl1];
[txtDetailLbl1 release];
// cell.textLabel.text = [repArray objectAtIndex:indexPath.row];
//cell.detailTextLabel.text = [titleArray objectAtIndex:indexPath.row];
cell.imageView.image=[imagearray objectAtIndex:indexPath.row];
UIView *viewSelected = [[[UIView alloc] init] autorelease];
viewSelected.backgroundColor = [UIColor colorWithRed:224.0/255.0
green:229.0/255.0
blue:241.0/255.0
alpha:1.0];
cell.selectedBackgroundView = viewSelected;
cell.textLabel.highlightedTextColor=[UIColor colorWithRed:46.0/255.0
green:77.0/255.0
blue:141.0/255.0
alpha:1.0];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *tempUID = [uidArray objectAtIndex:indexPath.row];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:tempUCID forKey:#"corpUcid"];
[prefs setObject:#"PROFILER" forKey:#"selProfiler"];
CorpPrevFront *corpPrevFront = [[CorpPrevFront alloc]initWithNibName:#"CorpPrevFront" bundle:nil];
[self.navigationController pushViewController:corpPrevFront animated:NO];
[corpPrevFront release];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
//FOR VIEW
if (buttonIndex == 1 && [alertView tag] == 1) {
// IT WILL BE MATCH ON CorpPrevFront CLASS
}
//FOR DELETE
if(buttonIndex == 2 && [alertView tag] == 1){
} else if(buttonIndex == 1 && [alertView tag] == 2){
DeleteProfiler *delProfiler = [[DeleteProfiler alloc]init];
BOOL del = [delProfiler deleteProfiler:selectedCpUid];
//[delProfiler deleteProfiler:selectedCpUcid];
if (del == YES) {
[repArray removeObjectAtIndex:selectedIndexPath.section];
[businessArray removeObjectAtIndex:selectedIndexPath.row];
[titleArray removeObjectAtIndex:selectedIndexPath.row];
[ucidArray removeObjectAtIndex:selectedIndexPath.row];
[self.corporateTable reloadData];
}
}
}
I am trying to delete an array element from a method. If I execute the below line then the app crashes automatically in my iPod Touch. But it works fine in simulator without any errors.
[repArray removeObjectAtIndex:selectedIndexPath.row];
or
[repArray removeObjectAtIndex:0];
both crashes the app even if I have more than one elements in array.
When you app crashes like that, 99% of the time you are trying to remove an object beyond the bounds of array.

pushViewController:detail not pushing detailView

I had my app navigating views perfectly. Now, for some reason that I can't figure out, my detailView is not presenting on the pushViewController:detail method in my modal view.
I cannot figure out why it's not working any more. Any help would be appreciated. Thanks.
Here's the method:
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
Here's the class code. I'm not sure if I need to pass in a navigationController with modalView:
//
// ModalView.m
// DiningLog
//
// Created by Eric Rea on 10/10/11.
// Copyright 2011 Avid. All rights reserved.
//
#import "ModalView.h"
#import "DetailView.h"
#implementation ModalView
#synthesize tableView, excersizeName, numSets, time, restTime, dateFormatter, rating, excersizeArray, plistArray, numberWithBool;
-(IBAction) cancel:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
-(IBAction) save:(id)sender{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"ExcersizeList.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"Excersizes" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property list into dictionary object
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.plistArray = [NSMutableArray arrayWithArray:[temp objectForKey:#"Excersizes"]];
NSLog(#"The contents of plistArray is%#", plistArray);
// set the variables to the values in the text fields
self.excersizeArray = [[NSMutableArray alloc] initWithCapacity:4];
[excersizeArray addObject:excersizeName];
[excersizeArray addObject:numSets];
[excersizeArray addObject:time];
[excersizeArray addObject:restTime];
[plistArray addObject:excersizeArray];
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: plistArray, nil] forKeys:[NSArray arrayWithObjects: #"Excersizes", nil]];
NSString *error = nil;
// create NSData from dictionary
// NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistDict)
{
// write plistData to our Data.plist file
[plistDict writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
[error release];
}
[self dismissModalViewControllerAnimated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tView {
// Return the number of sections.
return 1;
}
-(void)setObject:(id)object forNum:(int)num{
if(num == 0){
self.excersizeName = object;
NSLog(#"res %#", self.excersizeName);
}else if(num == 1){
self.numSets = object;
NSLog(#"res %#", self.numSets);
}else if(num == 2){
self.time = object;
NSLog(#"res %#", self.time);
}else if(num == 3){
self.restTime = object;
NSLog(#"res %#", self.restTime);
}else if(num == 4){
self.rating = [object floatValue];
}
[tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 5;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.row == 0){
cell.textLabel.text = #"Excersize";
cell.detailTextLabel.text = excersizeName;
}
if(indexPath.row == 1){
cell.textLabel.text = #"Sets";
cell.detailTextLabel.text = numSets;
}
if(indexPath.row == 2){
cell.textLabel.text = #"Time";
cell.detailTextLabel.text = time;
}
if(indexPath.row == 3){
cell.textLabel.text = #"Rest";
cell.detailTextLabel.text = restTime;
}
if(indexPath.row == 4){
cell.textLabel.text = #"Rating";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%f",rating];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (NSDateFormatter *)dateFormatter {
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
}
return dateFormatter;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Have you debugged and checked that your navigationController isn't nil ?
I figured it out. I accidentally erased the method insertNewObject in my rootViewController. When I rewrote it, I forgot to add in ModalView * modal = [[ModalView alloc] init];. That was the problem.
Here's what the method looks like now that it's working:
- (void)insertNewObject {
ModalView * modal = [[ModalView alloc] init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:modal];
[self presentModalViewController:controller animated:YES];
}

message sent to deallocated instance (probably UITableViewCell)

I know that a lot of folks have had this problem before and I've read a lot of suggested solutions, none of which has worked out for me. I'm working on a part of a larger project, involving three different views: the first view contains a UITableView with custom made cells called WeekdaySelectionWithPopoverCellController. This cell contains a label designating the weekday (Monday through Friday), a UISwitch and the following elements that are displayed or hidden respectively based on the state of the switch. If the switch is on, the cell looks like this:
----------------------------------------------------------------------
| Monday [ON/off] between ( N/A ) and ( N/A ) |
----------------------------------------------------------------------
If it's off it looks like this:
----------------------------------------------------------------------
| Monday [on/OFF] |
----------------------------------------------------------------------
The (N/A) elements are UIButtons. If the user hits one of those buttons a UIPopover with a date picker opens. The idea is that the user selects a time from the picker that should be displayed on the UIButtons instead of the (N/A):
----------------------------------------------------------------------
| Monday [ON/off] between ( 12:30 ) and ( 16:00 ) |
----------------------------------------------------------------------
The hiding of the elements on hitting the UISwitch works as does the display of the popover. However, if the user hits the "Done" button in the popover and the popover is dismissed the app crashes with the following error:
-[UITableViewCell isKindOfClass:]: message sent to deallocated instance 0xf42a100
Strangely enough the only place containing code that calls isKindOfClass is ModalTableViewController (the parent view of the popover and the custom cells) and the address of the instance displayed does not belong to it. Neither is it the address of the popover which only leaves the class of the custom cells (WeekdaySelectionWithPopoverCellController).
Let me give you the relevant parts of the ModalTableViewController.m:
#implementation ModalTableViewController
#synthesize mtvcNavigationBar;
#synthesize mtvcTableView;
#synthesize cell;
#synthesize lable;
#synthesize button;
// WeekdaySelectionWithPopoverCell
#synthesize wswpMainLabel;
#synthesize wswpFromLabel;
#synthesize wswpToLabel;
#synthesize wswpOClockFromLabel;
#synthesize wswpOClockToLabel;
#synthesize wswpSwitch;
#synthesize wswpFromValueButton;
#synthesize wswpToValueButton;
#synthesize popoverController;
// more code...
- (ModalTableViewController *)initWithParam:(NSString *)title andData:(NSArray *)myData andSelection:(NSArray *)selection {
[self initSwipeLeftNavigation];
mtvcNavigationBar.topItem.title = title;
mtvcSectionSize = [myData count];
mtvcSectionname = #"";
mtvcLabels = myData;
mtvcData = selection;
[mtvcLabels retain];
[mtvcData retain];
[otherValues retain];
mtvSingleton = [ModalTableViewSingleton sharedInstance];
return self;
}
// more code...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cellRet;
NSString *MyIdentifier = #"WeekdaySelectionWithPopoverCellController";
cellRet = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cellRet == nil) {
[[NSBundle mainBundle] loadNibNamed:MyIdentifier owner:self options:nil];
cellRet = self.cell;
}
NSDictionary *tempValues;
tempValues = [mtvcData objectAtIndex:indexPath.row];
wswpSwitch = (UISwitch *)[cellRet viewWithTag:2];
wswpSwitch.on = [[tempValues valueForKey:#"company_id"] isKindOfClass:[NSNull class]] ? false: true;
BOOL negatedState = !wswpSwitch.on;
NSLog(#"tempValues: %#", tempValues);
lable = (UILabel *)[cellRet viewWithTag:1];
lable.text = [NSString stringWithFormat:#"%#", [tempValues valueForKey:#"short"]];
lable.font = [UIFont boldSystemFontOfSize:16];
lable = (UILabel *)[cellRet viewWithTag:3];
lable.font = [UIFont boldSystemFontOfSize:16];
lable.text = [NSString stringWithFormat:#"%#", #"von"];
lable.hidden = negatedState;
lable = (UILabel *)[cellRet viewWithTag:5];
lable.text = [NSString stringWithFormat:#"%#", #"bis"];
lable.font = [UIFont boldSystemFontOfSize:16];
lable.hidden = negatedState;
lable = (UILabel *)[cellRet viewWithTag:7];
lable.text = #"Uhr";
lable.font = [UIFont boldSystemFontOfSize:16];
lable.hidden = negatedState;
lable = (UILabel *)[cellRet viewWithTag:8];
lable.text = #"Uhr";
lable.font = [UIFont boldSystemFontOfSize:16];
lable.hidden = negatedState;
button = (UIButton *)[cellRet viewWithTag:4];
[self setButtonLabel:button forKey:#"beginning" fromDict:tempValues];
button.hidden = negatedState;
/*
if (![[tempValues valueForKey:#"beginning"] isKindOfClass:[NSNull class]]) {
button.titleLabel.text = [NSString stringWithFormat:#"%#", [tempValues valueForKey:#"beginning"]];
} else {
button.titleLabel.text = #"k.A.";
}
*/
button = (UIButton *)[cellRet viewWithTag:6];
[self setButtonLabel:button forKey:#"until" fromDict:tempValues];
button.hidden = negatedState;
/*
if (![[tempValues valueForKey:#"until"] isKindOfClass:[NSNull class]]) {
button.titleLabel.text = [NSString stringWithFormat:#"%#", [tempValues valueForKey:#"until"]];
} else {
button.titleLabel.text = #"k.A.";
}
*/
self.cell = nil;
return cellRet;
}
- (void)setButtonLabel:(UIButton *)btn forKey:(NSString *)key fromDict:(NSDictionary *)dict {
[btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
NSString *text = [dict objectForKey:key];
if ([mtvSingleton.sharedData objectForKey:key]) {
[btn setTitle:[mtvSingleton.sharedData objectForKey:key] forState:UIControlStateNormal];
} else {
if ([text isKindOfClass:[NSNull class]] ||
[text isEqualToString:#""])
{
[btn setTitle:#"k.A." forState:UIControlStateNormal];
} else {
[btn setTitle:text forState:UIControlStateNormal];
}
}
}
// more code...
- (IBAction)switchButtonValueChanged:(id)sender
{
//[self changeDisplayState:wsdSwitch.on forObj:sender];
// UISwitch *tmp = (UISwitch *)sender;
UIView *v = (UIView *)sender;
do {
v = v.superview;
} while (![v isKindOfClass:[UITableViewCell class]]);
// WeekdaySelectionWithPopoverCellController *cell1 = (WeekdaySelectionWithPopoverCellController *)v;
cell = (UITableViewCell *)v;
wswpSwitch = (UISwitch *)[cell viewWithTag:2];
BOOL negatedState = !wswpSwitch.on;
lable = (UILabel *)[cell viewWithTag:3];
lable.hidden = negatedState;
lable = (UILabel *)[cell viewWithTag:5];
lable.hidden = negatedState;
lable = (UILabel *)[cell viewWithTag:7];
lable.hidden = negatedState;
lable = (UILabel *)[cell viewWithTag:8];
lable.hidden = negatedState;
button = (UIButton *)[cell viewWithTag:4];
button.hidden = negatedState;
button = (UIButton *)[cell viewWithTag:6];
button.hidden = negatedState;
/*
wswpSwitch = (UISwitch *)[cell1 viewWithTag:2];
BOOL negatedState = !wswpSwitch.on;
lable = (UILabel *)[cell1 viewWithTag:3];
lable.hidden = negatedState;
lable = (UILabel *)[cell1 viewWithTag:5];
lable.hidden = negatedState;
lable = (UILabel *)[cell1 viewWithTag:7];
lable.hidden = negatedState;
lable = (UILabel *)[cell1 viewWithTag:8];
lable.hidden = negatedState;
button = (UIButton *)[cell1 viewWithTag:4];
button.hidden = negatedState;
button = (UIButton *)[cell1 viewWithTag:6];
button.hidden = negatedState;
*/
}
#pragma mark - handlers
- (IBAction)toButtonHandler:(id)sender {
dppvc = [[DatePickerPopoverViewController alloc] initWithCaller:self andKey:#"beginning"];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:dppvc];
popover.delegate = self;
self.popoverController = popover;
[popover release];
[self.popoverController presentPopoverFromRect:[(UIButton *)sender frame]
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
- (IBAction)fromButtonHandler:(id)sender {
dppvc = [[DatePickerPopoverViewController alloc] initWithCaller:self andKey:#"until"];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:dppvc];
popover.delegate = self;
self.popoverController = popover;
[popover release];
CGRect senderFrameRect = [(UIButton *)sender frame];
[self.popoverController presentPopoverFromRect:senderFrameRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
#pragma mark - UIPopoverControllerDelegate
//---called when the user clicks outside the popover view---
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController {
// NSLog(#"popover about to be dismissed");
return YES;
}
//---called when the popover view is dismissed---
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
// NSLog(#"popover dismissed");
}
- (void)dismissPopover {
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
int i;
for (i = 0; i < [mtvcLabels count]; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[mtvcTableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:YES];
}
}
- (void)dealloc {
[mtvcSectionname release];
[mtvcLabels release];
[mtvcData release];
[cell release];
[super dealloc];
}
The crash occurs in main.m:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// crashes:
int retVal = UIApplicationMain(argc, argv, nil, nil); // <--
[pool release];
return retVal;
}
I have enabled NSZombieEnabled, MallocStackLoggingNoComp and NSAutoreleaseFreedObjectCheckEnabled but the compiler doesn't give me any more information than what I posted.
I've spent the entire day trying to resolve this but to no avail. Any hint in the right direction is appreciated!
I've been able to take care of this particular error. The problem was that cellRet in cellForRowAtIndexPath had not been retained. The following snippet resolves the error mentioned above:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cellRet;
NSString *MyIdentifier = #"WeekdaySelectionWithPopoverCellController";
cellRet = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cellRet == nil) {
[[NSBundle mainBundle] loadNibNamed:MyIdentifier owner:self options:nil];
cellRet = self.cell;
[cellRet retain];
}
// ...
}
Now however, I'm stuck with a new, similar error. This time it says:
*** -[CALayer release]: message sent to deallocated instance 0xc656d30
The following topic has some more information on the problem: "[CALayer release]: message sent to deallocated instance" when dismissing modal view controller
I have tried to change the property of the popover view controller to assign instead of retain but that gave me the message sent to deallocated instance error again, this time for the popover view controller.
Somebody with an idea? TIA!
The way I usually handle this is to create a subclass of UITableViewCell for my custom cells. and use the nib. I create a custom init that loads the cell from the nib. as follows.
- (id)init
{
self = [[[[NSBundle mainBundle] loadNibNamed:#"NibName" owner:self options:nil] objectAtIndex:0] retain];
if (self)
{
// any further initialization
}
return self;
}
in the nib set the cell's class to your new class.
then to use your cell do the following.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[[CustomCell alloc] init] autorelease];
}
// setup your cell
return cell;
}
You should definitely be using assign on your delegate properties.