In my code I store in the memory my array... To obtain it without make an HTML Request.
the first time, when I populated my array everything is ok... the problems show up when I load array from the memory and load them in a table.
That's the class
#interface SubscriptionArray : NSObject{
NSString *title;
NSString *source;
NSString *htmlUrl;
NSInteger count;
}
#property (nonatomic,retain) NSString *title;
#property (nonatomic,retain) NSString *source;
#property (nonatomic,retain) NSString *htmlUrl;
#property (nonatomic) NSInteger count;
#end
#import "SubscriptionArray.h"
#implementation SubscriptionArray
#synthesize title,source,htmlUrl,count;
-(void)dealloc{
[title release];
[source release];
[htmlUrl release];
}
#pragma mark NSCoding
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
title = [[decoder decodeObjectForKey:#"title"] retain];
source = [[decoder decodeObjectForKey:#"source"] retain];
htmlUrl = [[decoder decodeObjectForKey:#"htmlUrl"] retain];
count = [decoder decodeIntegerForKey:#"count"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
if (title) [encoder encodeObject:title forKey:#"title"];
if (source) [encoder encodeObject:source forKey:#"source"];
if (htmlUrl) [encoder encodeObject:htmlUrl forKey:#"htmlUrl"];
if (count) [encoder encodeInteger:count forKey:#"count"];
}
The array is declared in the delegate (to share with 3 different classes) as
NSMutableArray *onlySubsriptions; #property(nonatomic, retain)
NSMutableArray *onlySubsriptions;
And I load it in this way
[onlySubsriptions removeAllObjects];
self.onlySubsriptions = [NSKeyedUnarchiver unarchiveObjectWithFile:fullFileName];
And I received an error in the cellForRowAtIndexPath
for example I'm sure that I have 2 elements, the cellForRowAtIndexPath throws an exception when it start to load the 1st element (element 0)... it says deallocated instance.
I'm sure that the problem is on the encoding because the 1st time when I get the array everything is fine... Problems show up only when the next time I load my array that I store locally.
**** MORE INFO ABOUT ******
**** cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TDBadgedCell *cell = [[[TDBadgedCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
SubscriptionArray * element=[[SubscriptionArray alloc]init];
if (indexPath.section==0) {
NSLog(#"CASO SPECIALELEMENTS");
element =[delegate.reader.specialElements objectAtIndex:[indexPath row]];
}
if (indexPath.section==1) {
NSLog(#"CASO CATEGORIA");
element =[delegate.reader.categories objectAtIndex:[indexPath row]];
}
if (indexPath.section==2) {
NSLog(#"CASO SUBSCRIPTIONS");
element =[delegate.reader.onlySubsriptions objectAtIndex:[indexPath row]];
}
To deal with this kind of exception, you can use malloc instrument to find out the zombie and fix it.
Product > Profile will launch Instruments and then you there should be a "Trace Template" named "Malloc". This question may be useful for you.
Related
In my app I parse an XML file then I would like to show the entry of this file in a UITableView. I found on the web how to make section in alphabetical order (like iPhone contacts), it works fine with my app. When i tap on a row in my tableview I want to display another ViewController, in which I will find some information about the row I tapped, but I'm having some problem: when I tap on a row the variable indexPath.row refers to the section and the information in new view controller aren't right. I will post here some screenshot to show you want I'm trying to explain.
In the following pictures you can see how the app should work:
In the following pictures you can see the error of my app:
You can see that in picture 1 the name is the same and in picture 2 you can see that the name it's wrong. I guess it depend on the variable indexPath.row. I will post here the code to create and populate the tableview:
#import "TableWasteViewController.h"
#import "WasteXmlParser.h"
#import "WasteDetailViewController.h"
#interface TableWasteViewController ()
#property(nonatomic,strong)NSArray *arrayWastes;
#property(nonatomic,strong)NSMutableArray *typeOfWaste;
#property(nonatomic,strong)NSMutableArray *typeOfBin;
#property(nonatomic,strong)NSMutableArray *indexWastes;
#property(nonatomic,strong)NSMutableArray *typeOfWasteBackup;
#end
#implementation TableWasteViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
WasteXmlParser *parser = [[WasteXmlParser alloc]init];
[parser parseWasteXml];
self.arrayWastes = [[NSArray alloc]init];
self.arrayWastes = [parser.arrayWastes mutableCopy];
self.indexWastes = [[NSMutableArray alloc]init];
self.typeOfWaste = [[NSMutableArray alloc]init];
self.typeOfBin = [[NSMutableArray alloc]init];
for (int i = 0; i < [self.arrayWastes count]; i++) {
[self.typeOfWaste addObject:[[self.arrayWastes objectAtIndex:i] objectForKey:#"type"]];
[self.typeOfBin addObject:[[self.arrayWastes objectAtIndex:i]objectForKey:#"place"]];
}
for (int i = 0; i < [self.typeOfWaste count]-1; i++) {
char alphabet = [[self.typeOfWaste objectAtIndex:i] characterAtIndex:0];
NSString *uniChar = [NSString stringWithFormat:#"%c", alphabet];
if (![self.indexWastes containsObject:uniChar]) {
[self.indexWastes addObject:uniChar];
}
}
self.typeOfWasteBackup = [self.typeOfWaste mutableCopy];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.indexWastes count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self.indexWastes objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *alphabet = [self.indexWastes objectAtIndex:section];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#",alphabet];
NSArray *wastes = [self.typeOfWaste filteredArrayUsingPredicate:predicate];
return [wastes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UIFont *myFont = [UIFont fontWithName:#"Arial" size:14.0];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *alphabet = [self.indexWastes objectAtIndex:[indexPath section]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *wastes = [self.typeOfWaste filteredArrayUsingPredicate:predicate];
if ([wastes count] > 0) {
NSString *cellValue = [wastes objectAtIndex:indexPath.row];
cell.textLabel.font = myFont;
cell.textLabel.numberOfLines = 2;
cell.textLabel.text = cellValue;
}
return cell;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.indexWastes;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableWaste indexPathForSelectedRow];
WasteDetailViewController *vc = segue.destinationViewController;
vc.typeOfWaste = [self.typeOfWaste objectAtIndex:indexPath.row];
vc.typeOfBin = [self.typeOfBin objectAtIndex:indexPath.row];
vc.urlPic = [self.arrayWastes[indexPath.row]objectForKey:#"imgUrl"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)backToHome:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
I hope you can help me to fix this issue. Thank you
Rows are indexed by section, i.e. the first item in each section has indexPath.row == 0. So in order to look up values in your flattened vc.typeOfWaste and vc.typeOfBin arrays, you're going to need to do something along the lines of your numberOfRowsInSection method, where you filter the flattened array by the alphabet character and then get the item of the filtered array using indexPath.row.
Overall, this approach seems rather messy, having to filter your data repeatedly. Your data structures don't map well to the problem being solved. I would recommend using the TLIndexPathTools data model TLIndexPathDataModel because it's specifically designed for tables and collection views, can organize your data into sections, and can look up items by index path. Would be happy to walk you through a refactor if you like.
It's because the arrays that you're using to pass the data to the WasteDetailViewController, which are "typeOfWaste, typeOfBin, and urlPic" aren't sorted. The sorted array is called "wastes", but it is only available within the numberOfRowsInSection and the cellForRowAtIndexPath methods. You need to be passing the data in the wastes array forward, so rather than sorting the wastes array all the time, just sort it once after you've loaded it.
Add this property:
#interface TableWasteViewController ()
#property (strong, nonatomic) NSArray *sortedWastes;
#end
Now in viewDidLoad
NSString *alphabet = [self.indexWastes objectAtIndex:section];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#",alphabet];
self.sortedWastes = [self.typeOfWaste filteredArrayUsingPredicate:predicate];
Finally, in prepareForSegue
vc.typeOfWaste = [self.sortedWastes objectAtIndex:indexPath.row];
Your problems all stem from the fact that you are displaying a sorted array, but the array that you are using to pass the data forward is the unsorted array, so the indexPath is completely useless.
Furthermore, your typeOfBin and urlPic are going to be wrong as well. You need to find some way to link all three of your arrays together, so that when you sort one, you sort them all. The method above only keeps your typeOfWaste array sorted.
I also faced this issue few days ago...u need to make one class set properties whatever you want and then add that object in one array after that u can sort array on one property then whole array will be sorted
#import <Foundation/Foundation.h>
#interface HomeFeed : NSObject
#property (nonatomic, copy) UIImage *ItemImage;
#property (nonatomic, copy) NSString *ItemTitle;
#property (nonatomic, copy) NSString *ItemDate;
#property (nonatomic, copy) NSString *ItemDescription;
#property (nonatomic, copy) NSString *ItemHours;
#property (nonatomic, copy) NSString *ItemID;
#property (nonatomic, copy) NSString *itemDetailUrl;
#property (nonatomic, copy) NSString *itemPerson;
#property (nonatomic, copy) NSString *itemThumbUrl;
#property (nonatomic, assign) int ItemDuration;
#end
#import "HomeFeed.h"
#implementation HomeFeed
#synthesize ItemTitle=_ItemTitle, ItemDate=_ItemDate, ItemImage=_ItemImage,ItemID=_ItemID,ItemDuration=_ItemDuration,ItemDescription,ItemHours=_ItemHours,itemDetailUrl,itemPerson,itemThumbUrl;
#end
NSArray*arr=[responseString JSONValue];
NSLog(#"Json Dictionary speakersss : %#",arr);
NSLog(#"Json arr count speaker : %i",arr.count);
for (int i=0; i<arr.count; i++) {
NSDictionary *dict=[[ NSDictionary alloc]init];
dict=[arr objectAtIndex:i];
HomeFeed *feed = [[HomeFeed alloc] init];
feed.ItemTitle = [NSString stringWithFormat:#"%#%#%#",[dict objectForKey:#"firstName"],#" ",[dict objectForKey:#"lastName"]];
feed.ItemDuration = [[NSString stringWithFormat:#"%#", [dict objectForKey:#"count"]] intValue];
feed.itemDetailUrl=[dict objectForKey:#"detailsUrl"];
[self.itemsDataArray addObject:feed];
[itemTitle addObject:feed.ItemTitle];
}
HomeFeed *feed = [[HomeFeed alloc] init];
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:#"ItemTitle" ascending:YES];
[self.itemsDataArray sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SpeakersCustomCell"];
cell.selectionStyle = NO;
cell.accessoryType = NO;
HomeFeed *feed = [self.itemsDataArray objectAtIndex:indexPath.row];
UIImageView *arrow = (UIImageView *)[cell viewWithTag:3];
arrow.image = [UIImage imageNamed:#"accessory.png"];
UILabel *lblLeft = (UILabel *)[cell viewWithTag:1];
UILabel *lblRight = (UILabel *)[cell viewWithTag:2];
lblLeft.text=feed.ItemTitle;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
HomeFeed *feed=(HomeFeed*)[self.itemsDataArray objectAtIndex:indexPath.row];
self.onlinDetail.strUrl=feed.itemDetailUrl;
NSString *key = #"OrientationStringValue";
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:feed.itemDetailUrl forKey:key];
[[NSNotificationCenter defaultCenter] postNotificationName:#"NotifSpeaker1" object:nil userInfo:dictionary];
}
I receive I EXC_BAD_ACCESS but i can't understand why.
this is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TDBadgedCell *cell = [[[TDBadgedCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
SubscriptionArray * element =[reader.subscriptions objectAtIndex:[indexPath row]];
[cell.textLabel setText:element.title]; // <--- error at this line of code
return cell;
}
reader.subscritions is NSMutableArray that contains 81 elements ( I'm sure verificated with a NSLog) but when I try to get set the title I have this error... why?
SubscritionArray is a custom class that contains 3 string and 1 int.
Custom class:
header
#import <Foundation/Foundation.h>
#interface SubscriptionArray : NSObject{
NSString *title;
NSString *source;
NSString *htmlUrl;
NSInteger count;
}
#property (nonatomic,retain) NSString *title;
#property (nonatomic,retain) NSString *source;
#property (nonatomic,retain) NSString *htmlUrl;
#property (nonatomic) NSInteger count;
#end
implementation:
#import "SubscriptionArray.h"
#implementation SubscriptionArray
#synthesize title,source,htmlUrl,count;
-(void)dealloc{
[title release];
[source release];
[htmlUrl release];
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
title = [[decoder decodeObjectForKey:#"title"] retain];
source = [[decoder decodeObjectForKey:#"source"] retain];
htmlUrl = [[decoder decodeObjectForKey:#"htmlUrl"] retain];
//count = [decoder decodeIntForKey:#"count"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
if (title) [encoder encodeObject:title forKey:#"title"];
if (source) [encoder encodeObject:source forKey:#"source"];
if (htmlUrl) [encoder encodeObject:htmlUrl forKey:#"htmlUrl"];
//if (count) [encoder encodeInteger:count forKey:#"count"];
}
#end
EDIT
Tha's what I get
* -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0xe5a8260
And that's how I set the NSMutableArray
subscriptions = [[NSMutableArray alloc]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the
//documents directory:
NSString *fullFileName = [NSString stringWithFormat:#"%#/subscriptions", documentsDirectory];
[subscriptions removeAllObjects];
subscriptions = [NSKeyedUnarchiver unarchiveObjectWithFile:fullFileName];
I'd venture to say that your array of subscription elements isn't matching up with your row indexes (just a guess). Suggest that you set a debugger breakpoint immediately after you've declared 'element' and before you attempt to set the label. You should be able to see if you have actually obtained one of your SubscriptionArray objets...
The mutable array in reader.subscriptions is getting deallocated before you attempt to reference it in tableView:cellForRowAtIndexPath:. Make sure that the subscriptions array is properly retained or copied by the reader, and that you're not overreleasing it by sending an extra release or autorelease message somewhere. It might help to post the relevant code from the class of the reader instance.
I tried almost everything before posting (google, Apple Dev Doc etc.). I hope I did not miss anything before posting..
I already built a working JSON <-> Webservice <-> iPhone login.
with the following code:
NSString *responseString = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]autorelease];
NSDictionary *jsonDict = [responseString JSONValue];
NSString *loginResult = [jsonDict valueForKey:#"LoginResult"];
loginResult is the name of the employee: e.g "Henning Wenger"
The corresponding JSON looks like this:
{"LoginResult":"S:00000412"}
Now I have a more complex task which I can´t manage to figure a way through:
I´m getting the following JSON from the webservice:
{"GetTeamPresentStatusResult"[
{"Firstname":"Steffen","Id":"00000456","IsPresent":"true","Lastname":"Polker"},
{"Firstname":"Erich","Id":"00000455","IsPresent":"true","Lastname":"Welter"},
{"Firstname":"Titus","Id":"00000454","IsPresent":"true","Lastname":"Sommerbeck"}, {"Firstname":"Ruediger","Id":"00000453","IsPresent":"true","Lastname":"Oelmann"},{"Firstname":"Heinz","Id":"00000452","IsPresent":"true","Lastname":"Radelfs"},{"Firstname":"Franz","Id":"00000451","IsPresent":"true","Lastname":"Wippermann"},{"Firstname":"Klaus-Dieter","Id":"00000450","IsPresent":"true","Lastname":"Just"},{"Firstname":"Alan","Id":"00000412","IsPresent":"true","Lastname":"Turing"},{"Firstname":"Konrad","Id":"00000138","IsPresent":"true","Lastname":"Zuse"},{"Firstname":"Marius","Id":"00000112","IsPresent":"true","Lastname":"Sandmann"}]}
My code for handling this starts with:
NSDictionary *jsonDict = [responseString JSONValue];
NSArray *teamStatus = [jsonDict objectForKey:#"GetTeamPresentStatusResult"];
[self BuildDataSource: nil :teamStatus];
teamStatus now contains 10 key/value pairs.
Here is how I tried to build up the datasource for my table:
- (void)BuildDataSource: (id) sender: (NSArray*)teamStatusData{
teamStatusMutableArray = [[NSMutableArray alloc]init];
teamStatusDataSection = [[NSArray alloc]initWithArray:teamStatusData];
teamStatusDictSectionOne = [NSDictionary dictionaryWithObject:teamStatusDataSection forKey:#"OrgUnits"];
[teamStatusMutableArray addObject:teamStatusDictSectionOne];
[tblView reloadData];
}
I can not manage to figure out which way to go from here to get the data how I need it.
Do I need different Arrays where one contains the firstname/value and another one that contains lastname/value? If yes, how do I do that?
Here are some lines I´ve tried so far which did not have helped:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
//First get the dictionary object
NSDictionary *dictionary = [teamStatusMutableArray objectAtIndex:indexPath.section];
NSString *testString = [dictionary valueForKey:#"Firstname"];
NSArray *testarray = [dictionary objectForKey:#"OrgUnits"];
NSString *test = [testarray JSONRepresentation];
test = [test stringByReplacingOccurrencesOfString:#"[" withString:#""];
test = [test stringByReplacingOccurrencesOfString:#"]" withString:#""];
NSDictionary *jsonDict = [test JSONValue];
}
What I need is to have a Datasource with the Employee Names that I can bind to a Table. From there I think I can make my way without additional help.
I´m coming from the .NET (C#) world and maybe this confuses me too much.
Thank you so much..
Henning
If you need further details please ask!
Details for SPtail:
Here is the .h file:
#import <UIKit/UIKit.h>
#import "RootViewController.h"
#import "EmployeeDetails.h"
#interface OrgUnitAA:NSObject {
NSString *FirstName;
NSString *Id;
NSString *IsPresent;
NSString *LastName;
}
#property (nonatomic, retain) NSString *FirstName;
#property (nonatomic, retain) NSString *Id;
#property (nonatomic, retain) NSString *IsPresent;
#property (nonatomic, retain) NSString *LastName;
#end
#interface TeamStatusView : UIViewController {
UITableView *tblView;
NSMutableArray *teamStatusMutableArray;
NSArray *teamStatusDataSection;
NSDictionary *teamStatusDictSectionOne;
UIViewController *EmployeeDetails;
UIViewController *RootViewController;
NSMutableData *responseData;
}
#property (nonatomic, retain) IBOutlet UITableView *tblView;
#property (nonatomic, retain) NSArray *teamStatusMutableArray;
#property (nonatomic, retain) NSMutableArray *dummyMutableArrayTimeQuota;
#property (nonatomic, retain) NSArray *teamStatusDataSection;
#property (nonatomic, retain) NSDictionary *teamStatusDictSectionOne;
#property (nonatomic, retain) IBOutlet UIViewController *RootViewController;
#property (nonatomic, retain) IBOutlet UIViewController *EmployeeDetails;
- (void)GetTeamStatus: id;
- (void)BuildDataSource: id: (NSArray*)teamStatusData;
#end
Hey the array returned by the web service contains dictionaries, which is obvious.
Instead of using different arrays for each property, you can create a class which extends NSObject and convert each dictionary so that you will have the objects inside an array instead of dictionaries. In this case:
#interface OrgUnit:NSObject {
NSString *FirstName;
NSNumber *Id;
bool IsPresent;
NSString *LastName;
}
//And all the properties here
After this you can convert dictionaries into object by using
OrgUnit *unit = [[OrgUnit alloc] init];
[unit setValuesForKeysWithDictionary:dictionary];
PS: The variable names in the object should be same as that of the keys in dictionary
I´ve found a solution.
This is the way I get to the data:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
NSDictionary *dictionary = [teamStatusMutableArray objectAtIndex:indexPath.section];
NSArray *teamStatus = [dictionary objectForKey:#"OrgUnits"];
NSEnumerator *e = [teamStatus objectEnumerator];
id object;
int i = 0;
while (object = [e nextObject]) {
if(i == indexPath.row)
{
NSString *firstname = [object valueForKey:#"Firstname"];
NSString *lastname = [object valueForKey:#"Lastname"];
NSString *fullname = [NSString stringWithFormat:#"%#%#%#", lastname, #", ", firstname];
cell.textLabel.text = fullname;
bool isPresent = [object valueForKey:#"IsPresent"];
if(isPresent == true)
{
cell.imageView.image = [UIImage imageNamed:#"GreenBall.png"];
}
else
{
cell.imageView.image = [UIImage imageNamed:#"RedBall.png"];
}
break;
}
i++;
}
[aiActivity stopAnimating];
self.aiActivity.hidden = true;
return cell;
}
Could be just a typo.
Change this:
teamStatusDictSectionOne = [NSDictionary dictionaryWithObject:teamStatusDataSection forKey:#"OrgUnits"];
To this:
teamStatusDictSectionOne = [NSDictionary dictionaryWithObjects:teamStatusDataSection forKey:#"OrgUnits"];
The change is -dictionaryWithObjects. Plural. Obj-C is kinda finicky about that stuff.
Also, you are referencing indexPath.section when you build the individual cells. I think you should be referencing the row for the cell. The row should correlate to your array index.
NSInteger row = [indexPath row];
NSDictionary *dictionary = [teamStatusMutableArray objectAtIndex:row];
i have a memory leak in my app.
My app launches on a tableviewcontroller. i parse a json file to fill an array. Then this array is used to fill the tableview's cells.
I fill my array with objects (class).
I do:
[tab_Demandes removeAllObjects];
for (NSDictionary *demandeD in demandes)
{
Demande *dem =[[Demande alloc] init];
dem.demTitle=title;
dem.demId=Id;
dem.demCreated=created;
[tab_Demandes addObject:dem];
[dem release];
}
My array and tableview are filled at launch, no problem.
if i hit a table cell and then want to come back on the tableview my app crash on :
[tab_Demandes removeAllObjects];
If i dont do [dem release] i have leaks in instruments every time i reload tab_Demandes. RemoveAllObjects works but i have leaks.
Thx for any help as usual.
Wallou
++
Edit : here is where i made my cells. Maybe i mess up when creating the cells
Actually tab_Demandes is declared in the delegate with get/set to access it from other classes (where i load my tableviewcontroller).
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomCellViewController *cell = (CustomCellViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// NSLog(#"Cell created");
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCellViewController" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[CustomCellViewController class]])
{
cell = (CustomCellViewController *)currentObject;
break;
}
}
}
// Set up the cell...
TabsAppDelegate *appDelegate = (TabsAppDelegate*)[[UIApplication sharedApplication] delegate];
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row ] demId]];
cell.lbl_demCopro .text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demIdCopro ]];
cell.lbl_demImmeuble.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demIdImmeuble]];
cell.lbl_demLot.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demIdLot]];
cell.lbl_demDescriptif.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demTitle]];
//NSLog(#"statut demande : %#",[[tab_Demandes objectAtIndex:indexPath.row] demStatut]);
if ([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Validée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"VDEM2.png"];
}
if([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Initiée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"IDEM.png"];
}
if([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"Terminée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"TDEM.png"];
}
if([[[[appDelegate tab_Demandes] objectAtIndex:indexPath.row] demStatut] isEqualToString: #"En coursée"])
{
cell.lbl_ImageView.image=[UIImage imageNamed:#"EDEM.png"];
}
return cell;
}
NEW EDIT:
Demandes.h:
#interface Demande : NSObject {
NSString *demId;
NSString *demStatut;
NSString *demTitle;
NSString *demCreated;
NSString *demIdCopro;
NSString *demIdImmeuble;
NSString *demIdLot;
NSString *demDescriptif;
NSString *demAuteur;
NSString *demIdAuteur;
NSString *demLoginAuteur;
}
#property (retain,nonatomic) NSString *demId;
#property (retain,nonatomic) NSString *demIdCopro;
#property (retain,nonatomic) NSString *demIdImmeuble;
#property (retain,nonatomic) NSString *demIdLot;
#property (retain,nonatomic) NSString *demDescriptif;
#property (retain,nonatomic) NSString *demStatut;
#property (retain,nonatomic) NSString *demTitle;
#property (retain,nonatomic) NSString *demCreated;
#property (retain,nonatomic) NSString *demAuteur;
#property (retain,nonatomic) NSString *demIdAuteur;
#property (retain,nonatomic) NSString *demLoginAuteur;
#end
Demandes.m:
import "Demande.h"
#implementation Demande
#synthesize demId,demIdCopro,demIdImmeuble,demIdLot,demDescriptif,demStatut,demTitle,demCreated,demAuteur,demIdAuteur,demLoginAuteur;
- (void)dealloc {
[demId release];
[demIdCopro release];
[demId release];
[demIdImmeuble release];
[demIdLot release];
[demDescriptif release];
[demStatut release];
[demTitle release];
[demCreated release];
[demAuteur release];
[demIdAuteur release];
[demLoginAuteur release];
[super dealloc];
}
#end
The code above is correct. I wondering if you don't over release objects that are in you array (i.e. during tableView:cellForRowAtIndexPath method). When calling removeAllObject, the method release every object it removes. If one object is already released and deallocated, you app will crash.
Proposed Optimization :
-Be sure that the cellIdentifier in the nib is well #"Cell"
-Replace
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row ] demId]];
by
Demand* dem = [[[appDelegate tab_Demandes] objectAtIndex:indexPath.row ];
cell.lbl_demId.text=[NSString stringWithFormat:#"%#", [dem demId]];
to avoid querying the array too much time.
-Avoid placing your model in the appDelegate and create a singleton model object instead. This is a common beginner design mistake driven by the fact that the appDelegate is an easy object to customize and access to avoid passing you model to every objects.
I have made some progress and am editing the question to be current again. My big issue now is that the grouped table view will load, but shows all of everything in each section with each row. Also, my UIAlertView is returning all references to my plist (null). How would I fix this because the references to the plist are killing me. Any and all help would be greatly appreciated!
Here is the plain text version of my plist file:
<array>
<dict>
<key>eventName</key>
<string>Comedy Caravan</string>
<key>eventSpecifics</key>
<string>Nicholas Anthony</string>
<key>eventLocation</key>
<string>The Cats Den</string>
<key>eventType</key>
<string>Comedy</string>
<key>eventGoodies</key>
<string>Both</string>
<key>eventDate</key>
<date>2010-07-23T00:00:00Z</date>
</dict>
<dict>
<key>eventName</key>
<string>Comedy Caravan</string>
<key>eventLocation</key>
<string>The Cats Den</string>
<key>eventType</key>
<string>Comedy</string>
<key>eventSpecifics</key>
<string>Bruce Baum</string>
<key>eventGoodies</key>
<string>Prizes</string>
<key>eventDate</key>
<date>2010-07-24T00:00:00Z</date>
</dict>
<dict>
<key>eventName</key>
<string>Late Night Film Series</string>
<key>eventLocation</key>
<string>The Cats Den</string>
<key>eventType</key>
<string>Comedy</string>
<key>eventSpecifics</key>
<string>Avatar</string>
<key>eventGoodies</key>
<string>Food</string>
<key>eventDate</key>
<date>2010-07-24T02:00:00Z</date>
</dict>
</array>
Here is my ThisWeekViewController.h:
#import <UIKit/UIKit.h>
#class Event;
#interface ThisWeekViewController : UITableViewController
{
NSArray *eventNames;
Event *event;
}
#property (nonatomic, retain) NSArray *eventNames;
#property (nonatomic, retain) Event *event;
#end
and Here is my ThisWeekViewController.m:
#import "ThisWeekViewController.h"
#import "Event.h"
#implementation ThisWeekViewController
#synthesize eventNames;
#synthesize event;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Events" ofType:#"plist"];
NSArray *dict = [[NSArray alloc] initWithContentsOfFile:path];
NSArray *namesArray = [dict valueForKey:#"eventName"];
self.eventNames = namesArray;
[dict release];
[self.tableView reloadData];
}
- (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.
self.eventNames = nil;
}
#pragma mark Table View Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.eventNames count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *key = [NSString stringWithFormat:#"%#", event.eventName];
return key;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.eventNames count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
// Set the cell's text to the event name
cell.textLabel.text = event.eventName;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
- (void)dealloc {
// [thisWeek release];
[event release];
[eventNames release];
[super dealloc];
}
#end
I have also included my Event.h file
#import <Foundation/Foundation.h>
#interface Event : NSObject {
NSString *eventName;
NSString *eventType;
NSDate *eventDate;
NSString *eventLocation;
NSString *eventGoodies;
NSString *eventSpecifics;
}
- (id)initWithDictionary:(NSDictionary *)aDictionary;
#property (nonatomic, retain) NSString *eventName;
#property (nonatomic, retain) NSString *eventType;
#property (nonatomic, retain) NSString *eventLocation;
#property (nonatomic, retain) NSDate *eventDate;
#property (nonatomic, retain) NSString *eventGoodies;
#property (nonatomic, retain) NSString *eventSpecifics;
#end
and my Event.m file
#import "Event.h"
#implementation Event
#synthesize eventName;
#synthesize eventType;
#synthesize eventDate;
#synthesize eventLocation;
#synthesize eventGoodies;
#synthesize eventSpecifics;
- (id)initWithDictionary:(NSDictionary *)aDictionary {
if ([self init]) {
self.eventName = [aDictionary valueForKey:#"eventName"];
self.eventType = [aDictionary valueForKey:#"eventType"];
self.eventDate = [aDictionary valueForKey:#"eventDate"];
self.eventLocation = [aDictionary valueForKey:#"eventLocation"];
self.eventGoodies = [aDictionary valueForKey:#"eventGoodies"];
self.eventSpecifics = [aDictionary valueForKey:#"eventSpecifics"];
}
return self;
}
- (void)dealloc {
[eventName release];
[eventType release];
[eventDate release];
[eventLocation release];
[eventGoodies release];
[eventSpecifics release];
[super dealloc];
}
#end
I would like to be able to place things such as cell.detailTextLabel.text = event.eventSpecifics and just run off of references like that.
If I recall correctly, UITableViewController reloads the table view in -viewWillAppear:. This may very well be called before -viewDidLoad is called. I would recommend that you insert a call to [self.tableView reloadData] at the end of your implementation of -viewDidLoad.
You should also be calling [super viewDidLoad] at the top of your implementation of -viewDidLoad, and similarly for -viewDidUnload.
Also, you don't need to declare your class as conforming to UITableViewDataSource or UITableViewDelegate as your superclass (UITableViewController) already does that for you.