iphone detailtext in UITableView question - iphone

So, I am able to create an array that populates the fields of the Table, but am having troubles creating the subtext that appears below the main fields. I currently have:
- (void)viewDidLoad {
[super viewDidLoad];
listOfForms = [[NSMutableArray alloc] init];
[listOfForms addObject:#"First Form"];
}
and then:
NSString *cellValue = [listOfDAForms objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
in the cellForRowAtIndexPath portion. Why can't I add:
listOfNames = [[NSMutableArray alloc] init];
[listOfNames addObject:#"Named Form"];
and
NSString *cellSubscript = [listOfNames objectAtIndex:indexPath.row];
cell.detailTextLabel.text = cellSubscript;
in order to make the little subview work? What am I doing wrong?

Be sure to init your cell with the style UITableViewCellStyleSubtitle

Related

retrieved data from sqlite database and displaying it on grouped table view

hii every one
i am brand new to obj c, i have did a sample project where i have 2 screens on the first screen i have six text fields & 2 buttons named save and ViewData ,on click of save data which is entere d in the text field will be get saved in the sqliteData Base ,& on click of the button ViewData it will navigate to a new screen which has a grouped table view, here i am trying to display the data which is stored in the sqlite ,in the grouped table view i have 6 sections i am using following code to display the data in grouped table view,problem is grouped table view is displaing only the last data which is entered ih the text field,,but i need to display all the data which enterd should be shown under that section
appDelegate = (iICS_testAppDelegate *)[[UIApplication sharedApplication] delegate];
for(int intVar=0;intVar < [appDelegate.arrObjects count];intVar++)
{
insertUpdateDelete *InsertRecord = [appDelegate.arrObjects objectAtIndex:intVar];
NSLog(#"InsertRecord:%#",InsertRecord);
NSMutableArray *arrTemp1 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strsixth,nil];
NSMutableArray *arrTemp2 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strfifth,nil];
NSMutableArray *arrTemp3 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strFourth,nil];
NSMutableArray *arrTemp4 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strLogin,nil];
NSMutableArray *arrTemp5 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strMiddleName,nil];
NSMutableArray *arrTemp6 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strFirstName,nil];
NSMutableDictionary *temp =[[NSMutableDictionary alloc]initWithObjectsAndKeys:arrTemp1,#"Item Name",arrTemp2,#"Manufacturer",arrTemp3,#"Weight of Item",arrTemp4,#"Num of Item",arrTemp5,#"Price of Item",arrTemp6,#"MFG Date",nil];
self.tableContents =temp;
[temp release];
NSLog(#"table %#",self.tableContents);
NSLog(#"table with Keys %#",[self.tableContents allKeys]);
self.sortedKeys =[[self.tableContents allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sorted %#",self.sortedKeys);
[arrTemp1 release];
[arrTemp2 release];
[arrTemp3 release];
[arrTemp4 release];
[arrTemp5 release];
[arrTemp6 release];
}
here im assigning the text for the row
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//insertUpdateDelete *InsertRecord = [appDelegate.arrObjects objectAtIndex:indexPath.row];
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self.tableContents objectForKey:[self.sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
//cell.textLabel.text = [appDelegate.arrObjects objectAtIndex:row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
thanks in advance!
This is my snapshopt of grouped table view. I need the data which is entered through the text field shoul be viewed under particular section
Solution for only the last data is displaying,
Instead of NSArray use NSMutableArray.
Solution for wrong field values,
Your problem may be in insertion itself,
NSArray *arrTemp1 = [[NSArray alloc]initWithObjects:InsertRecord.strsixth,nil];
NSArray *arrTemp2 = [[NSArray alloc]initWithObjects:InsertRecord.strfifth,nil];
You are inserting price value into date field, i think so. Please check that.
Change your code as,
NSMutableArray *arrTemp1 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp2 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp3 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp4 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp5 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp6 = [[NSMutableArray alloc]init];
for(int intVar=0;intVar < [appDelegate.arrObjects count];intVar++)
{
insertUpdateDelete *InsertRecord = [appDelegate.arrObjects objectAtIndex:intVar];
NSLog(#"InsertRecord:%#",InsertRecord);
[arrTemp1 addObject:InsertRecord.strsixth];
[arrTemp2 addObject:InsertRecord.strfifth];
[arrTemp3 addObject:InsertRecord.strFourth];
[arrTemp4 addObject:InsertRecord.strLogin];
[arrTemp5 addObject:InsertRecord.strMiddleName];
[arrTemp6 addObject:InsertRecord.strMiddleName];
}
NSDictionary *temp =[[NSDictionary alloc]initWithObjectsAndKeys:arrTemp1,#"Item Name",arrTemp2,#"Manufacturer",arrTemp3,#"Weight of Item",arrTemp4,#"Num of Item",arrTemp5,#"Price of Item",arrTemp6,#"MFG Date",nil];
self.tableContents =temp;
[temp release];
NSLog(#"table %#",self.tableContents);
NSLog(#"table with Keys %#",[self.tableContents allKeys]);
self.sortedKeys =[[self.tableContents allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sorted %#",self.sortedKeys);
[arrTemp1 release];
[arrTemp2 release];
[arrTemp3 release];
[arrTemp4 release];
[arrTemp5 release];
[arrTemp6 release];

NSMutableArray, pList, Tableview muddle and meltdown

I have a preferences view which shows a different table view depending on which Segmented Control is clicked.
I hard coded some NSMutableArrays to test basic principles:
prefsIssuesList = [[NSMutableArray alloc] init];
[prefsIssuesList addObject:#"Governance"];
[prefsIssuesList addObject:#"Innovation and technology"];
...etc
prefsIndustriesList = [[NSMutableArray alloc] init];
[prefsIndustriesList addObject:#"Aerospace and defence"];
... etc
prefsServicesList = [[NSMutableArray alloc] init];
[prefsServicesList addObject:#"Audit and assurance"];
...etc
currentArray = [[NSMutableArray alloc] init];
currentArray = self.prefsIssuesList;
Then reload the tableview with currentArray, adding a UITableViewCellAccessoryCheckmark.
Everything works fine.
But now I want to store wether the checkmark is on or off in a pList file, and read this back in.
Ideally want to a plist like this
Root Dictionary
Issues Dictionary
Governance Number 1
Innovation and technology Number 0
etc
I've got as far as working this out
// Designate plist file
NSString *path = [[NSBundle mainBundle] pathForResource: #"issues" ofType:#"plist"];
// Load the file into a Dictionary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.allNames= dict;
[dict release];
NSLog(#"Dict is %#", allNames); // All the data in the pList file
NSMutableArray *issueSection = [allNames objectForKey:#"Issues"];
NSLog(#"Issues is %#", issueSection); // The data is the Issues Section
NSString *issueVal = [issueSection objectForKey:#"Governance"];
NSLog(#"Governance is %#", issueVal); //The value of the Governance key
But what I really want to do is loop through the Issues Dictionary and get the key/value pairs so
key = cell.textLabel.text
value = UITableViewCellAccessoryCheckmark / UITableViewCellAccessoryNone
depending wether it's 1 or 0
I'm assuming that I can still assign one of the three NSMutableArrays to currentArray as I did in the hardcoded version, and use currentArray to reload the tableview.
Then amend this code to build the tableview
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *CellIdentifier = #"Cell";
//UITableViewCell *cell = [self.prefsTableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
UITableViewCell *cell = [self.prefsTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell=[[[UITableViewCell alloc]
initWithFrame:CGRectZero
reuseIdentifier: CellIdentifier] autorelease];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
But my brain has melted, I've spent about six hours today reading up on pLists, NSArrays, NSMutableDisctionaries, standardUserDefaults to little avail.
I've managed to UITableViews inside UINavigationViews, use SegmentedControls, download asynchronous XML, but now I'm finally stuck, or fried, or both. Over what should be fairly simple key/value pairs.
Anyone care to give me some idiot pointers?
Typing it out led to another post with that one little word I needed to get me back on track :)
Use key/value pairs in a pList to stipulate the name of the cell and wether it was selected or not by the user.
plist is based on a structure like this
Root Dictionary
Services Dictionary
Peaches String 1
Pumpkin String 0
Here's how I grabbed three Dictionary arrays from a pList and used the key/value pairs to reload a tableview depending on which segmentControl was touched:
- (void)viewDidLoad {
[super viewDidLoad];
// Designate plist file
NSString *path = [[NSBundle mainBundle] pathForResource: #"issues" ofType:#"plist"];
// Load the file into a Dictionary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.allNames= dict;
[dict release];
// Create the Named Dictionaries from Dictionary in pLIst
NSMutableDictionary *allIssues = [self.allNames objectForKey:#"Issues"];
self.prefsIssuesList = allIssues;
[allIssues release];
NSMutableDictionary *allIndustries = [self.allNames objectForKey:#"Industries"];
self.prefsIndustriesList = allIndustries;
[allIndustries release];
NSMutableDictionary *allServices = [self.allNames objectForKey:#"Services"];
self.prefsServicesList = allServices;
[allServices release];
// Assign the current Dictionary to out placeholder Dictionary
currentDict = [[NSMutableDictionary alloc] init];
currentDict = self.prefsIssuesList;
}
Then styling the table cells
- (UITableViewCell *)tableView:(UITableView *)prefsTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSArray *keysArray = [self.currentDict allKeys];
NSString *theKey = [keysArray objectAtIndex:row];
NSString *theValue = [self.currentDict objectForKey: [keysArray objectAtIndex:row]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.prefsTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell=[[[UITableViewCell alloc]
initWithFrame:CGRectZero
reuseIdentifier: CellIdentifier] autorelease];
}
cell.textLabel.text = theKey;
if (theValue == #"0") {
cell.accessoryType = UITableViewCellAccessoryNone;
}else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
return cell;
}
The if clause at the end doesn't seem to be working, I'll post that as a new question (unless anyone comments quickly!)
Finally the segmentControls assign the different dictionaries to the placeholder array and reload the tableview
This took me a very long day to figure out (as a noobie) so I hope it helps someone
-(IBAction) segmentedControlIndexChanged{
switch (self.segmentedControl.selectedSegmentIndex) {
case 0:
//currentArray = self.prefsIssuesList;
currentDict = self.prefsIssuesList;
break;
case 1:
//currentArray = self.prefsIndustriesList;
currentDict = self.prefsIndustriesList;
break;
case 2:
//currentArray = self.prefsServicesList;
currentDict = self.prefsServicesList;
break;
default:
//currentArray = self.prefsIssuesList;
currentDict = self.prefsIssuesList;
break;
}
[prefsTableView reloadData];
}
Shout if there's a neater or better way of d

Setting dictionary in singleton causing EXC_BAD_ACCESS

I'm having issues with a singleton I've created. It contains two NSMutableDictionary's, which are read and used in three views (and some modal views) throughout the app.
I've added an MKMapView t plot some of the venues inside the dictionaries on a map. When I use the exact same method/function used in every other view to access the data, I receive an EXC_BAD_ACCESS error pertaining to a deallocated dictionary. This comes from NSZombieEnabled:
CFDictionary retain: message sent to deallocated instance
In a dsym'ed trace, it is the replacement of one dictionary with another that is causing grief. The code I'm using to call the function comes from a MKAnnotationView click:
UIControl *tempButton = sender;
NSString *selectedEventsString = [self.eventsArray objectAtIndex:tempButton.tag];
NSLog(#"eventString: %#", selectedEventsString);
[[EventsManager eventsManager] changeSelectedEventsDictionaryTo:selectedEventsString];
[tempButton release];
[selectedEventsString release];
"selectedEventsString" is coming out to a perfectly corresponding event.
The corresponding code in EventsManager:
-(void)changeSelectedEventsDictionaryTo:(NSString *)eventName {
NSLog(#"singleton: %#", eventName);
self.eventString = eventName;
self.selectedEventsDictionary = [self.eventsDictionary objectForKey:eventName];
}
Both selectedEventsDictionary and eventsDictionary are set as #property (nonatomic, retain) in the .H file, and this is the init function:
+ (EventsManager*)eventsManager {
if (eventsManager == nil) {
eventsManager = [[super allocWithZone:NULL] init];
eventsManager.eventsDictionary = [[NSMutableDictionary alloc] init];
eventsManager.selectedEventsDictionary = [[NSMutableDictionary alloc] init];
eventsManager.eventString = [[NSString alloc] init];
eventsManager.mode = [[NSString alloc] init];
}
return eventsManager;
}
This is an example of code used in other views that works fine:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSString *eventString = [self.eventsArray objectAtIndex:row];
[[EventsManager eventsManager] changeSelectedEventsDictionaryTo:eventString];
//Modal display code here
}
Any help would be greatly appreciated! I think I've provided all relevant code but let me know if more is needed.
Cheers!
Where to start! I will point out some things that I do see wrong.
First Example. Do not release tempButton and selectedEventString as you never explicitly called retain/copy or alloc and init on them.
UIControl *tempButton = sender;
NSString *selectedEventsString = [self.eventsArray objectAtIndex:tempButton.tag];
NSLog(#"eventString: %#", selectedEventsString);
[[EventsManager eventsManager] changeSelectedEventsDictionaryTo:selectedEventsString];
//DO NOT RELEASE THESE YOU NEVER RETAINED THEM!
[tempButton release];
[selectedEventsString release];
Your static eventsManager is not thread safe which may not be a issue for you but should definitely be looked into.
Read the comments for the following code example
+ (EventsManager*)eventsManager {
if (eventsManager == nil) { //<-- Not thread safe
//DO NOT CALL SUPER USE self
//eventsManager = [[self alloc] init];
eventsManager = [[super allocWithZone:NULL] init];
//You need to autorelease these values or use an autoreleased static method
//eventsManager.eventsDictionary = [NSMutableDictionary dictionary];
//eventsManager.selectedEventsDictionary = [NSMutableDictionary dictionary];
eventsManager.eventsDictionary = [[NSMutableDictionary alloc] init];
eventsManager.selectedEventsDictionary = [[NSMutableDictionary alloc] init];
//Do not bother setting these at all or just set them to nil
eventsManager.eventString = [[NSString alloc] init];
eventsManager.mode = [[NSString alloc] init];
}
return eventsManager;
}
Make sure all of those properties are set to retain or copy and that may fix your problem. If you still have an issue after these fixes you can update your question and I will update my answer.

Memory leaks in UITableView with NSMutableArray - How to stop them?

I'm pretty new to objective-c development and I'm to the point I'm beginning to test my application for leaks and patching up anything else I may have done wrong originally. I followed the examples from a book I bought and expanded on those ideas. The Leaks instrument is telling me in my tableView cellForRowAtIndexPath method I have a leak and I'm not sure on how to fix it.
Here is the related .h contents:
#interface NewsListViewController : UITableViewController<UIActionSheetDelegate> {
NSMutableArray *newsList, *account, *playerList;}
And here is the related .m contents:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)ip {
static NSString *CellIdentifier = #"NewsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
[cell autorelease];
}
NSManagedObject *uNews = [newsList objectAtIndex:[ip row]];
NSManagedObjectContext *playerDBContext = [[AppController sharedAppController] managedObjectContext];
NSFetchRequest *playerDBRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *playerDBEntity = [NSEntityDescription entityForName:#"Players"
inManagedObjectContext:playerDBContext];
[playerDBRequest setEntity:playerDBEntity];
NSPredicate *playerDBPredicate = [NSPredicate predicateWithFormat:#"playerID=%#", [uNews valueForKey:#"playerID"]];
[playerDBRequest setPredicate:playerDBPredicate];
NSError *playerDBError;
NSArray *playerDBList = [playerDBContext executeFetchRequest:playerDBRequest error:&playerDBError];
[playerDBRequest release];
playerList = [playerDBList mutableCopy];
NSString *playerInformation;
if (![playerDBList count] == 0) {
NSManagedObject *playerInfo = [playerList objectAtIndex:0];
playerInformation = [NSString stringWithFormat:#"%#, %# (%#-%#)", [playerInfo valueForKey:#"playerLastName"],
[playerInfo valueForKey:#"playerFirstName"],
[playerInfo valueForKey:#"team"],
[playerInfo valueForKey:#"position"]];
} else {
//NSInteger playerID = (NSInteger *)[uNews valueForKey:#"playerID"];
[self addPlayer:(NSInteger *)[uNews valueForKey:#"playerID"]];
NSLog(#"%#", [uNews valueForKey:#"playerID"]);
playerInformation = [uNews valueForKey:#"playerInfo"];
}
cell.textLabel.text = playerInformation;
cell.detailTextLabel.text = [uNews valueForKey:#"news"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;}
It's throwing the error on the playerList = [playerDBList mutableCopy]; line - Help with how to fix and an explanation would be greatly appreciated. It's probably from reallocating without releasing but when I've tried using [playerList release]; at the end of the cellForRowAtIndexPath my app crashes.
Properties would make this 'just work'.
.h:
...
#property (nonatomic, retain) NSMutableArray *playerList;
...
.m:
#implementation MyClass
#synthesize playerList;
... then in your cellForIndexPath method ...
self.playerList = [[playerDBList mutableCopy] autorelease];
...
- (void)dealloc {
[playerList release];
[super dealloc];
}
A property declared 'retain' will automatically handle memory management when the property is assigned, releasing the old value if it exists before retaining the new one.
The release you tried crashed because the first time through playerlist hasn't ever been assigned and you release a nil. But the second time through it has something and you leak it. Whenever I reuse a retaining pointer like that, I do
if( playerList )
[playerList release];
playerList = [playerDBList mutableCopy];
just to be safe.

NSKeyedUnarchiver - Bad access

I was trying to archive an object into a plist file and load it later to fill a tableView.
It seems that the file gets archived correctly but I get a bad access when trying to get the value out of the file.
Am I doing something wrong?
This is where I save it
// Create some phonebook entries and store in array
NSMutableArray *book = [[NSMutableArray alloc] init];
Phonebook *chris = [[Phonebook alloc] init];
chris.name = #"Christian Sandrini";
chris.phone = #"1234567";
chris.mail = #"christian.sandrini#example.com";
[book addObject:chris];
[chris release];
Phonebook *sacha = [[Phonebook alloc] init];
sacha.name = #"Sacha Dubois";
sacha.phone = #"079 777 777";
sacha.mail = #"info#yzx.com";
[book addObject:sacha];
[sacha release];
Phonebook *steve = [[Phonebook alloc] init];
steve.name = #"Steve Solinger";
steve.phone = #"079 123 456";
steve.mail = #"steve.solinger#wuhu.com";
[book addObject:steve];
[steve release];
[NSKeyedArchiver archiveRootObject:book toFile:#"phonebook.plist"];
And here I try to get it out of the file and save it back into an array
- (void)viewDidLoad {
// Load Phone Book
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithFile:#"phonebook.plist"];
self.list = arr;
[arr release];
[super viewDidLoad];
}
The part where I try to build a cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PhoneBookCellIdentifier = #"PhoneBookCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PhoneBookCellIdentifier];
if ( cell == nil )
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:PhoneBookCellIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
Phonebook *book = [self.list objectAtIndex:row];
cell.textLabel.text = book.name;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
Here the bad access error
Current language: auto; currently
objective-c Assertion failed: (cls),
function getName, file
/SourceCache/objc4_Sim/objc4-427.5/runtime/objc-runtime-new.mm,
line 3990. Assertion failed: (cls),
function getName, file
/SourceCache/objc4_Sim/objc4-427.5/runtime/objc-runtime-new.mm,
line 3990. Assertion failed: (cls),
function getName, file
/SourceCache/objc4_Sim/objc4-427.5/runtime/objc-runtime-new.mm,
line 3990. Assertion failed: (cls),
function getName, file
/SourceCache/objc4_Sim/objc4-427.5/runtime/objc-runtime-new.mm,
line 3990.
Just to expand on that a fraction: unarchiveObjectWithFile will return an autoreleased pointer. You don't locally retain it so you shouldn't release. Because you do, the object is subsequently deallocated and by the time you come to use it by calling book.name, it's not there.
(I'm assuming the self.list property is retaining appropriately so that the object will be kept around as long as you don't release here. If not, you'll need to fix that too.)