object crashes Application - iphone

i got an NSArray which gets filled in the init Method of my UITableViewController.
i use this object in "didSelectRowAtIndexPath" for pushing another tableviewcontroller.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ablogSingleCatTableViewController *singleCatTableViewController = [[ablogSingleCatTableViewController alloc] initWithStyle:UITableViewStylePlain category:[categories objectAtIndex:indexPath.row]];
[[self navigationController] pushViewController:singleCatTableViewController animated:YES];
[singleCatTableViewController release];
}
this works a few times when i start my application. after selecting a row and getting back to the main uitableview controller at a rondom point my application crashes after selecting a row.
with some nslogs i found out, that it crashes if i try to use my "categories" object.
so
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"before");
NSLog(#"cats: %#", categories);
NSLog(#"after");
ablogSingleCatTableViewController *singleCatTableViewController = [[ablogSingleCatTableViewController alloc] initWithStyle:UITableViewStylePlain category:[categories objectAtIndex:indexPath.row]];
[[self navigationController] pushViewController:singleCatTableViewController animated:YES];
[singleCatTableViewController release];
}
with that code my application crashes after "before" ... "after" never shows up.
i dont know why my "categories" object is crashing my application ?!
my categories object is defined in my header file and has a #property (nonatomic, retain). i synthesize it and releasing it in my dealloc method.
anyone has an idea?
// edit:
some more details here, because of the comments:
Debugger Console says: "Program received signal: “EXC_BAD_ACCESS”.
i create the category array like this:
- (void)initCategories {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Categories" ofType:#"plist"];
[self setCategories:[[NSArray alloc] initWithContentsOfFile:path]];
}
calling this method in my initwithstyle method
[self initCategories];
my other custom initializing method looks something like this:
- (id)initWithStyle:(UITableViewStyle)style category:(NSDictionary*)cat {
if (self = [super initWithStyle:style]) {
currentCategory = cat;
items = [[NSMutableArray alloc] init];
self.title = [currentCategory objectForKey:#"TITLE"];
//XLog("%#", currentCategory);
}
return self;
}

ok, first thing is ;
[self setCategories:[[NSArray alloc] initWithContentsOfFile:path]];
you have a leak here. just use
categories = [[NSArray alloc] initWithContentsOfFile:path];
Crash occurs in here;
currentCategory = cat;
you have to retain, use;
currentCategory = [cat retain];
These are the problems I see in posted code, if you have not any mistake in the rest of the program, it should be fine with these fixes.

If you are creating your array something like this:
NSArray *tmpArray = [[NSArray alloc] initWithBlah ...];
Make sure that you assign it using the synthesized getter by using this code:
self.categories = tmpArray;
[tmpArray release];
If you do:
categories = tmpArray;
[tmpArray release];
the instance variable will not be retained at all.

Related

how parse value of array of one class to other and other to another?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1 && indexPath.row == 0) {
NSString *requestString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/xml?origin=%#&destination=%#,OK&sensor=false",startField.text,endField.text];
NSURL *url = [[NSURL alloc] initWithString:requestString];
NSData *tempData =[[NSData alloc] initWithContentsOfURL:url];
NSString *Str = [[NSString alloc] initWithData:tempData encoding:NSUTF8StringEncoding];
NSLog(#"%#",Str);
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
xml1 *parser = [[xml1 alloc] init];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success){
NSLog(#"No Errors");
arySteps=[[NSMutableArray alloc]init];
arySteps=[parser.ListofSteps1 mutableCopy];
}
else
NSLog(#"Error Error Error!!!");
controller.arayStep=[[NSMutableArray alloc]init];
controller.arayStep=[parser.ListofSteps1 copy];
controller= [[TableView alloc] initWithNibName:#"TableView" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
In above code i have parsed XML data. In XML-parser file i have store objects in array that is ListofSteps1. Now i access in root-view controller class which is shown in above code. So in root-view class ListofSteps1 assign value to array of root-view controller. Now i want to assign value of array of root-view controller to next view's array which is also maintain in above code but array of next view is not getting value. What is problem in this code so it not getting value?
There are a couple of things wrong with your code above. You alloc and init a fresh array only to write over it on two separate occasions in your method implementation:
arySteps=[[NSMutableArray alloc]init]; // This line serves absolutely no purpose
arySteps=[parser.ListofSteps1 mutableCopy]; // This line is sufficient on its own
Calling accessor methods on an null pointer will do you absolutely no good. You need to instantiate the object before you attempt to set its properties:
controller= [[TableView alloc] initWithNibName:#"TableView" bundle:nil];
controller.arayStep=[parser.ListofSteps1 copy];
These mistakes are very basic and indicate that you need to work on the fundamentals before you can get too much further. I would suggest that you pick up a good book on Objective-C - for example, Programming in Objective-C by Stephen Kochan - and read it thoroughly. A solid understanding of the core concepts will serve you well going forward.

Struggling with memory management and create array method

I'm struggling to find the correct way to release an array after my method has been called. I wonder if there is a better way to achieve what I'm trying to acheive with my method:
- (NSArray *) setupDetailArray : (NSString *) selectedCategory {
// Load .plist file
NSString *path = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
// Load .plist into a new dictionary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
// Drill down to next level
NSArray *faceSelection = [[NSArray alloc] initWithArray:[dict objectForKey:detailTitle]];
[dict release], dict = nil;
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
dataCenter.faces = [[NSMutableArray alloc] init];
// Set app delegate faces to array
dataCenter.faces = faceSelection;
[dataCenter.faces release];
return faceSelection;
// [faceSelection release], faceSelection = nil; ??????
}
And I call my method in viewDidLoad
// If faceArray is empty, create it
if (faceArray == nil)
faceArray = [self setupDetailArray:detailTitle];
...
My application is leaking memory here, and I'm really looking for a way to release everything once I'm done.
Your method should return an autoreleased array which is then retained by the method that calls it if it wants/needs to keep it.
- (NSArray *) setupDetailArray : (NSString *) selectedCategory {
...
// Create the array, but don't own it
NSArray *faceSelection = [[[NSArray alloc] initWithArray:[dict objectForKey:detailTitle]] autorelease];
...
return facesSelected;
}
Now the code that calls this method should retain the object if it needs it. So, in your viewDidLoad
if (faceArray == nil)
faceArray = [[self setupDetailArray:detailTitle] retain];
...
If faceArray is an instance variable in your class, then you can just release it in your dealloc method.
You are also leaking memory here
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
dataCenter.faces = [[NSMutableArray alloc] init];
// Set app delegate faces to array
dataCenter.faces = faceSelection;
[dataCenter.faces release];
This should be
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
dataCenter.faces = faceSelection;
I'd suggest you read (and re-read and re-read) the docs on memory management and read up on properties, setters and the dot notation.
Apple Objective-C Memory Management
dataCenter.faces = [[NSMutableArray alloc] init];
You allocate a non-autoreleased array and assign it to the property faces (I bet it has the retain modifier).
dataCenter.faces = faceSelection;
Now you assign as new array to the faces property, but you haven't properly release the previous NSMutableArray.
[dataCenter.faces release];
You now indirectly release your faceSelection array.
You leak at least one NSMutableArray every time you run that method. You should do it like this instead:
// Drill down to next level
NSArray *faceSelection = [[dict objectForKey:detailTitle] copy];
[dict release], dict = nil;
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
// Set app delegate faces to array
dataCenter.faces = faceSelection;
return [faceSelection autorelease];
Your method should return an autoreleased object. The only methods that should return retained objects are methods whose name:
starts with alloc
starts with new
contains copy
All other methods should return autoreleased objects.
Other way for doing this.
//Declare method as follows.
- (void) setupDetailArray : (NSString *) selectedCategory arrFaceArray:(NSArray *)faceArray
{
}
And I call my method in viewDidLoad
if (!faceArray)
{
faceArray = [[NSArray alloc] init]; //Alloc in ViewDidLoad and release in ViewDidUnload or dealloc.
faceArray = [self setupDetailArray:detailTitle arrFaceArray:faceArray];
}
Also consider the #DarkDust answer for maintaining autoreleased objects. Both are the possible ways.

NSMutableArray not accessible throughout my class?

I'm really frustrated after spending like three hours googling around to solve this problem!! It's probably an easy solution to it aswell.
I'm creating a really simple TableView app for the iPhone. It's supposed to fetch an XML-document and parse it (already fixed) and then put the data into objects called HPobject!
One HPobject represents one day of data from the XML-file. Anyhow!
Then I want the object to be stored in a NSMutableArray so I can grab it later when I'm creating the table rows. But I can't access it! My NSMutableArray is ALWAYS null! No matter what I do!
Here's my code:
//THE .h FILE
#import "TBXML.h"
#import "HPobject.h"
#interface RootViewController : UITableViewController {
NSMutableArray *listOfItems;
}
- (void)traverseElement:(TBXMLElement *)element;
//THE .m FILE
#import "RootViewController.h"
#import "HPobject.h"
#implementation RootViewController
- (void)viewDidLoad
{
NSMutableArray *listOfItems = [[NSMutableArray alloc] init];
TBXML * tbxml = [[TBXML tbxmlWithURL:[NSURL URLWithString:#"http://www.hpprov.se/istasts.php?q=xxxxxxx"]] retain];
if (tbxml.rootXMLElement)
[self traverseElement:tbxml.rootXMLElement]; //Works fine!
[tbxml release];
[super viewDidLoad];
}
- (void) traverseElement:(TBXMLElement *)element {
do {
//Lots of parsing code which all works fine and gets me the variables up next!
HPobject *currentObject = [[HPobject alloc] init];
currentObject.antalRegistrerade = numRegistrerade;
currentObject.inkomstBrutto = numBrutto;
currentObject.inkomstNetto = numNetto;
[listOfItems addObject:currentObject];
NSLog(#"Array: %#", listOfItems); //RETURNS null!
NSLog(#"Reg: %#, Net: %#, Brutt: %#", currentObject.antalRegistrerade, currentObject.inkomstNetto, currentObject.inkomstBrutto); //Returns the correct values!
NSLog(#"%d stycken!", listOfItems.count); //Returns 0!! :(
[currentObject release];
} while ((element = element->nextSibling));
}
You are defining listOfItems locally in viewDidLoad and then you try to access that in another method.
Make sure you are using an instance variable defined in your interface definition (header).
replace this line in viewDidLoad:
NSMutableArray *listOfItems = [[NSMutableArray alloc] init];
with
listOfItems = [[NSMutableArray alloc] init];
I suppose that listOfItems is an ivar. So to fix your problem change this:
NSMutableArray *listOfItems = [[NSMutableArray alloc] init];
to this
listOfItems = [[NSMutableArray alloc] init];
Take a look at the scope of your array. You have created that as a variable of another method. It will not visible in others. Make an instance var.

iPhone - Objective-C - Memory Leak with initWithArray

I am using the code below to set my two NSArray ivars:
The issue is, I keep getting a memory leak on the following lines:
followingFriendsArray = [[NSArray alloc] initWithArray:friend.Following];
followerFriendsArray = [[NSArray alloc] initWithArray:friend.Followers];
Is this not the correct way to set ivars from an existing NSArray of items? Any help would be appreciated. I've also tried to autorelease the above two lines, but when I actually access them in another method I get an error that they've already been released.
I have included my Interface and Implementation code below:
Interface .h:
NSArray *followingFriendsArray;
NSArray *followerFriendsArray;
#property (nonatomic, retain) NSArray *followingFriendsArray;
#property (nonatomic, retain) NSArray *followerFriendsArray;
Implementation .m:
- (void)handlerGetFollowingInformation:(id)value {
BOOL success = [Utility checkWebServiceErrors:value controller:self.navigationController];
if (success) {
Friend *friend = (Friend *)value;
followingFriendsArray = [[NSArray alloc] initWithArray:friend.Following];
followerFriendsArray = [[NSArray alloc] initWithArray:friend.Followers];
}
}
This is how I need to access the arrays:
- (void)followersButtonTapped:(id)sender {
FollowingVC *fvc = [[FollowingVC alloc] initWithNibName:#"FollowingViewController" bundle:nil];
fvc.friends = followerFriendsArray;
[self.navigationController pushViewController:fvc animated:YES];
[fvc release];
}
I release my two ivars in the following way as per usual:
- (void)viewDidUnload {
self.followingFriendsArray = nil;
self.followerFriendsArray = nil;
[super viewDidUnload];
}
- (void)dealloc {
[followingFriendsArray release];
[followerFriendsArray release];
[super dealloc];
}
I mean the code works just fine, it's just that I'm concerned about said memory leaks when I run the "Leaks" performance tool.
OK
you should not use autorelease in this case, but you have to release the arrays by calling :
[followingFriendsArray release];
[followerFriendsArray release];
you can do it:
when you don't need to use them any more.
in the dealloc method in your .m file.
option 2looks like that -
- (void)dealloc {
[followingFriendsArray release];
[followerFriendsArray release];
[super dealloc];
}
BTW -
if you don't manipulate the arrays after creating them (add / remove objects) you should use an immutable array (NSArray).
Good Luck
Your method handlerGetFollowingInformation is assigning new values to followingFriendsArray and followerFriendsArray without releasing the previous contents. If you call this method more than once on the same instance you will leak.
CRD is right that the arrays are not released inside the handlerGeFollowingInformation method but the fix is maybe overkill. What you need to do is to use self. so that the setter method is called which does that automatically. You could should look like this:
- (void)handlerGetFollowingInformation:(id)value {
BOOL success = [Utility checkWebServiceErrors:value controller:self.navigationController];
if (success) {
Friend *friend = (Friend *)value;
self.followingFriendsArray = [[NSArray alloc] initWithArray:friend.Following];
self.followerFriendsArray = [[NSArray alloc] initWithArray:friend.Followers];
}
}
Easy fix but hard to spot and I ran into this issue over and over again especially when I started to dealloc are the properties.
-Andy

iPhone Core Data problems

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *selectedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
BlogRssParser *blogRss = [[BlogRssParser alloc] init];
[blogRss setSelectedObject:selectedObject];
RssFunViewController *rssFun = [[RssFunViewController alloc] initWithNibName:#"RssFunViewController" bundle:nil];
[self.navigationController pushViewController:rssFun animated:YES];
[rssFun release];
}
This is my code so when the user taps the row, its supposed to take the value from the row and insert it into here:
NSString *terms = [[[self selectedObject] valueForKey:#"data"]description];
NSLog(#"%#", terms);
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://news.search.yahoo.com/rss?ei=UTF-8&p=%#&fr=news-us-ss", terms]];
But "terms" is showing up as (null) in the log? Not the value of the clicked row
I see, that u used some codes, I posted here for you. But you shouldnt just copy and paste it.
In my code selectedObject is not a member, as it is absolutely not necessary.
This line
NSManagedObject *selectedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
points to a non-member variable
while
[self selectedObject]
points to a member — a totally different thing.
edit
Is the second part in the TableViewContoller or in the DetailedView?