avoid auto release of NSMutable array..... iphone app - iphone

I have a NSmutablearray
after i read datas from it, i cant read the same data(index) again
Error:
"EXC_BAD_ACCESS"
in interface
NSMutableArray *ticketList;
#property (nonatomic, retain) NSMutableArray *ticketList;
assigning value
self.ticketList = [NSMutableArray arrayWithArray:[results objectForKey:#"tickets"]];
reading value
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ticketCell";
ticketCell *cell = (ticketCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[self.cellNib instantiateWithOwner:self options:nil];
cell = tmpCell;
self.tmpCell = nil;
}
else {
// Nothing to do here. Because in either way we change the values of the cell later.
}
cell.useDarkBackground = (indexPath.row % 2 == 0);
// Configure the data for the cell.
int rowID = indexPath.row;
NSDictionary *currentTicket = [ticketList objectAtIndex:(int)(indexPath.row)];
NSString *tikid = [currentTicket objectForKey:#"number"];
cell.ticketID = [currentTicket objectForKey:#"number"];
cell.ticketStatus = [currentTicket objectForKey:#"status"];
cell.ticketOpenDate = [currentTicket objectForKey:#"oDate"];
cell.ticketEndDate = [currentTicket objectForKey:#"eDate"];
cell.ticketCategory = [currentTicket objectForKey:#"category"];
cell.ticketPriority = [currentTicket objectForKey:#"priority"];
cell.ticketInfo = [currentTicket objectForKey:#"info"];
return cell;
}

You have to alloc array properly:
ticketList = [[NSMutableArray alloc] initWithArray:[results objectForKey:#"tickets"]];
And also maybe try to alloc currentTicket:
NSDictionary *currentTicket = [[NSDictionary alloc] initWithDictionary:[ticketList objectAtIndex:indexPath.row]];

Sounds like somewhere you're doing something like this:
[currentTicket release];
If so, don't. The currentTicket pointer doesn't belong to you.

use this
ticketList = [[NSMutableArray alloc]initWithArray:[results objectForKey:#"tickets"]];
instead of
self.ticketList = [NSMutableArray arrayWithArray:[results objectForKey:#"tickets"]];
use this
NSDictionary *currentTicket = [ticketList objectAtIndex:indexPath.row];
instead of
NSDictionary *currentTicket = [ticketList objectAtIndex:(int)(indexPath.row)];

Related

Populating UITableView with NSArray in iOS 7

A lot of the methods have deprecated in iOS 7 in order to set font, textLabel, and color for UITableView cells. I'm also just having a difficult time populating the view with these values. Here's a snippet of my code:
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSArray* jobs = [json objectForKey:#"results"];
for(NSDictionary *jobsInfo in jobs) {
JobInfo *jobby = [[JobInfo alloc] init];
jobby.city = jobsInfo[#"city"];
jobby.company = jobsInfo[#"company"];
jobby.url = jobsInfo[#"url"];
jobby.title = jobsInfo[#"jobtitle"];
jobby.snippet = jobsInfo[#"snippet"];
jobby.state = jobsInfo[#"state"];
jobby.time = jobsInfo[#"date"];
jobsArray = [jobsInfo objectForKey:#"results"];
}
}
I am looping through an array of dictionaries from a GET request and parsed. I am now attempting to fill my UITableView with the following code:
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [jobsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *jobsDic = [jobsArray objectAtIndex:indexPath.row];
[cell.textLabel setText:[jobsDic objectForKey:#"jobtitle"]];
return cell;
}
Also, I have declared this is in my .h file:
NSArray *jobsDic;
Any ideas on what I'm doing wrong? Is this an iOS 7 problem?
It seems that you reinitialize jobsarray at the end of the forin loop.
You didn't mean ?
NSArray* jobs = [json objectForKey:#"results"];
NSMutableArray *jobsTemp = [[NSMutableArray alloc] initWithCapacity:jobs.count];
for(NSDictionary *jobsInfo in jobs) {
JobInfo *jobby = [[JobInfo alloc] init];
jobby.city = jobsInfo[#"city"];
jobby.company = jobsInfo[#"company"];
jobby.url = jobsInfo[#"url"];
jobby.title = jobsInfo[#"jobtitle"];
jobby.snippet = jobsInfo[#"snippet"];
jobby.state = jobsInfo[#"state"];
jobby.time = jobsInfo[#"date"];
[jobsTemp addObject:jobby];
}
self.jobsArray = jobsTemp; //set #property (nonatomic, copy) NSArray *jobsArray; in the .h
[self.tableView reloadData]; //optional only if the data is loaded after the view
In the cell for row method :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
JobInfo *job = self.jobsArray[indexPath.row];
cell.textLabel.text = job.title;
return cell;
}
And don't forget :
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.jobsArray.count;
}
Update - an user suggested an edit :
It's true that count isn't a NSArray property. But as Objective-C lets us use a shortcut notation for calling method with a dot, this code works. You have to know limitation of this : if you use a NSArray subclass with a count property with a custom getter this could have side effects #property (nonatomic, strong, getter=myCustomCount) NSUInteger count. As I think code readability is to me one of most important things I prefer to use dot notation. I think Apple SHOULD implement count as readonly property so I use it this way (but it's my point of view). So for those which don't agree with me just read return [self.jobsArray count]; in the tableView:numberOfRowsInSection: method.
Change the declaration of jobsArray from NSArray to NSMutableArray.
Add an initialization at the beginning point of fetchedData method like follows.
if(!jobsArray) {
jobsArray = [NSMutableArray array];
}
else {
[jobsArray removeAllObjects];
}
Remove the following line.
jobsArray = [jobsInfo objectForKey:#"results"];
Instead of that, add the initialized object to the array at the end of for loop.
[jobsArray addObject:jobby];
Add a [tableView reloadData]; at the end of your *-(void)fetchedData:(NSData )responseData; method implementation.
Initially when you are loading the view, tableView will get populated. After you received the data, tableView will not be known that it is received.
Everything else seems good. Hope rest will work fine.

Uitableview displaying objects

I want to display the values of a NSMutableArray in a UITableView. In the NSMutableArray are values of objects. But the UITableView doesn't display anything. If I use a normal NSArray with static values it works well.
So this is my code:
This is my object
#interface Getraenke_Object : NSObject {
NSString *name;
}
my NSMutableArray
NSMutableArray *getraenkeArray;
here is where I get the values into the array:
for(int i = 0; i < [getraenkeArray count]; i++)
{
[_produktName addObject:[[getraenkeArray objectAtIndex:i]getName]];
NSLog(#"test: %#",_produktName);
}
and that is how I try to display it in the UITableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ProduktCell";
ProduktTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ProduktTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
int row = [indexPath row];
cell.produktName.text = _produktName [row];
return cell;
}
Just make your getraenkeArray as member and:
cell.produktName.text = [[getraenkeArray objectAtIndex:indexPath.row] getName];
it seems like you never allocated the NSMutableArray. you are missing:
_produktName = [NSMutableArray array];
and that's why the addObject is being sent to nil..

Why am I seeing a crash when displaying this table view?

I am designing a simple navigation based application for EmployeeContactDirectory. I am displaying the list of Employee. For showing the list of employee, I am using the restfull webservice. I am getting proper response as I want. I have a utility class for Employee Data, class is EmployeeData.h and Employee.m (contains employeeId , employeeFirstName, employeeLastName). My code for parsing
// Code for parsing the response and getting desired field into the dictionary object and add the dictionaries into the array.
-(void)finishedReceivingData:(NSData *)data {
NSData *dataRes = [[restConnection stringData] dataUsingEncoding:NSUTF8StringEncoding];
////////////////Parsing with XPathQuery Start//////////////////////
if (dataRes != NULL) {
employeeData = [[EmployeeData alloc] init];
NSString *xPathQuery = [NSString stringWithFormat:#"/*",employeeData.employeeID];
NSArray *arrayWithObjectList = PerformXMLXPathQuery(dataRes, xPathQuery);
for(NSDictionary *childOfObjectList in arrayWithObjectList){
NSArray *arrayOfDataValueObj = (NSArray *)[childOfObjectList objectForKey:#"nodeChildArray"];
for(NSDictionary *childObjListDict in arrayOfDataValueObj){
NSArray *childObjListDataValue = (NSArray *)[childObjListDict objectForKey:#"nodeChildArray"];
for(NSDictionary *childDict in childObjListDataValue){
if([[childDict objectForKey:#"nodeName"] isEqualToString:#"FName" ])
{
employeeData.employeeFirstName = [childDict objectForKey:#"nodeContent"];
}
if([[childDict objectForKey:#"nodeName"] isEqualToString:#"EmpID"])
{
employeeData.employeeID = [childDict objectForKey:#"nodeContent"];
}
}
//employeeFirstNameArray = [NSArray arrayWithObjects:employeeData, nil];
employeeIDArray = [NSArray arrayWithObjects:employeeData, nil];
dictionaryEmployeeFirstName = [NSDictionary dictionaryWithObject:employeeData.employeeFirstName forKey:#"employeeData"];
dictionaryEmployeeID = [NSDictionary dictionaryWithObject:employeeData.employeeID forKey:#"employeeData"];
tempArray = [NSArray arrayWithObjects:dictionaryEmployeeFirstName, dictionaryEmployeeID, nil];
NSLog(#"size of temp %d",[tempArray count]);
}
}
//[employeeData release];
//employeeData = nil;
}
[self.tableviewEmloyeeList reloadData];
//////////////////////////////Parsing with XPathQuery end//////////
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell..
NSDictionary *dictionaryEmployee = [tempArray objectAtIndex:indexPath.row];
NSArray *firstNameArray = [dictionaryEmployee objectForKey:#"employeeData"];
NSString *cellValue = [firstNameArray objectAtIndex:indexPath.row];
NSLog(#"cellValue %#",cellValue);
cell.textLabel.text = cellValue;
return cell;
}
I am getting the message (Exc_bad_Access) when this line of code comes into the execution flow:
NSDictionary *dictionaryEmployee = [tempArray objectAtIndex:indexPath.row]
The EXC_Bad_Access is at the mail.m file at line nt retVal = UIApplicationMain(argc, argv, nil, nil);
So, Please tell me how can I set the data into the tableview when I am using NSDictionary. When, user clicks on the row of the tableview it will return the id of the selected employee.
Instead of the line
tempArray = [NSArray arrayWithObjects:dictionaryEmployeeFirstName, dictionaryEmployeeID, nil];
try the following,
if( tempArray )
{
[tempArray release];
tempArray = nil;
}
tempArray = [[NSArray arrayWithObjects:dictionaryEmployeeFirstName, dictionaryEmployeeID, nil] retain];
Since it is autoreleased, it might have been out of memory.
you need to implement a tableView delegate method called
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
here you will get the section & row clicked in the table

App crashing when scrolling TableView

My app is crashing when i scroll my TableView. First in my viewDidLoad method a load a dictionary from a file and for this dictionary i enumerate all keys.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
path = [rootPath stringByAppendingPathComponent:[NSString stringWithFormat:#"currency.archive"]];
banks = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
keys = [banks allKeys];
// set date for last update
dayMonthYear.text = [banks objectForKey:#"Last Updated"];
}
In my cellForRowAtIndexPath i populate cells with data from that dictionary. Anyway when my app starts everything looks fine, first five rows are drawn correctly, but when i start to scroll my app crash. My idea is that the problem is with autoreleased object here, i tried to retain them and after using them to release ,but unsuccessful. DEBUGGER SHOWS THAT MY PROBLEM IS AT LINE WITH BOLD
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell %d_%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CurrencyTableCell" owner:self options:nil];
cell = currencyTableCell;
//don't show selected cell
cell.selectionStyle = UITableViewCellSelectionStyleNone;
//set height
self.cellHeight = cell.frame.size.height;
}
// Fetch currency
NSString *currentCurrency = [keys objectAtIndex:indexPath.row];
NSDictionary *fetchedCurrency = [banks objectForKey:currentCurrency];
**NSString *name = [fetchedCurrency objectForKey:#"Currency Name"];**
currencyTitle.text = name;
NSString *charCode = [fetchedCurrency objectForKey:#"Code"];
currencyCode.text = charCode;
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f",[[fetchedCurrency objectForKey:#"Value"] floatValue]];
if ([formattedNumber length] == 4) {
formattedNumber = [NSString stringWithFormat:#"%#%#",#"0",formattedNumber];
}
buyPrice.text = formattedNumber;
return cell;
}
As a result from the discussion, [banks objectForKey:#"Last Updated"] gives you a NSString, not a NSDictionary!
You could get around this error by doing
if ([[banks objectForKey:currentCurrency] class] == [NSDictionary class]) {
... rest of the code here ..
}
Change your viewDidLoad with below code it will work
- (void)viewDidLoad {
[super viewDidLoad];
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
path = [rootPath stringByAppendingPathComponent:[NSString stringWithFormat:#"currency.archive"]];
banks = [[NSDictionary alloc] initWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithFile:path]];
keys = [[NSArray alloc] initWithArray:[banks allKeys]];
// set date for last update
dayMonthYear.text = [banks objectForKey:#"Last Updated"];
}
-[NSCFString objectForKey:]: unrecognized selector sent to instance
0x4bab9c0
Your banks and keys variables aren't retained, as mentioned in another answer, but this isn't the error.
As per this error, your fetchedCurrency object is an NSString, not an NSDictionary. Check the format of your currency.archive file.

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