I have this class
#import <Foundation/Foundation.h>
#interface SubscriptionArray : NSObject{
NSString *title;
NSString *source;
NSString *htmlUrl;
}
#property (nonatomic,retain) NSString *title;
#property (nonatomic,retain) NSString *source;
#property (nonatomic,retain) NSString *htmlUrl;
#end
and the implementation file is this one:
#import "SubscriptionArray.h"
#implementation SubscriptionArray
#synthesize title,source,htmlUrl;
-(void)dealloc{
[title release];
[source release];
[htmlUrl release];
}
#end
When I use the class like in this example I get an EXEC_BAD_ACCESS error:
for (NSDictionary *element in subs){
SubscriptionArray *add;
add.title=[element objectForKey:#"title"]; //ERROR Happens at this line
add.source=[element objectForKey:#"htmlUrl"];
add.htmlUrl=[element objectForKey:#"id"];
[subscriptions addObject:add];
}
Can someone help me?
P.S. Subscriptions is a NSMutableArray
You need to allocate your SubscriptionArray object like so: SubscriptionArray *add = [[SubscriptionArray alloc] init];
Your for loop will therefore look something like this:
for (NSDictionary *element in subs){
SubscriptionArray *add = [[SubscriptionArray alloc] init];
add.title=[element objectForKey:#"title"];
add.source=[element objectForKey:#"htmlUrl"];
add.htmlUrl=[element objectForKey:#"id"];
[subscriptions addObject:add];
[add release];
}
You need to initialize your SubscriptionArray. i.e.
SubscriptionArray *add = [SubscriptionArray new];
Related
In NSMutableArray or NSArray how do you set up the row structure. All the examples I can find just deal with one dimensional integers or strings.
So how do you go about setting up an array row structure like:
Integer, String, Date
You would need to create an array of arrays, or an array of dictionaries, the second approach being better if you'd like to refer to the data by name rather than index:
NSMutableArray *rows = [[NSMutableArray alloc] init];
NSMutableDictionary *firstRow = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:12], #"fieldWithNumber",
[NSString stringWithFormat:#"A formatted string %ld", 34], #"fieldWithString",
[NSDate date], #"fieldWithDate",
nil];
[rows addObject:firstRow];
// etc.
You can make custom class and add collection of these objects in an array.
For example please assume that we have to do some rows about places then create a class PLACE.h
#interface PLACE : NSObject
{
NSString *title;
NSString *summary;
NSString *url;
NSString *latitude;
NSString *longitude;
}
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *summary;
#property (nonatomic, retain) NSString *url;
#property (nonatomic, retain) NSString *latitude;
#property (nonatomic, retain) NSString *longitude;
#end
PLACE.m
#implementation PLACE
#synthesize title;
#synthesize summary;
#synthesize url;
#synthesize latitude;
#synthesize longitude;
- (void) dealloc
{
[title release];
[summary release];
[url release];
[latitude release];
[longitude release];
[super dealloc];
}
#end
Create instance of the class PLACE for each place and hold the objects in the array. I think that solves your problem.
An array is just a collection of objects.
Just create an object that has an integer, date and string and then add instances of those to the array.
I have made a very simple custom object pictureData.
Here is the .h file
#import <Foundation/Foundation.h>
#interface pictureData : NSObject {
NSString *fileName;
NSString *photographer;
NSString *title;
NSString *license;
}
#property (nonatomic, retain) NSString *fileName;
#property (nonatomic, retain) NSString *photographer;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *license;
+(pictureData*)picDataWith:(NSDictionary*)dictionary;
#end
The .m file
#import "pictureData.h"
#implementation pictureData
#synthesize fileName;
#synthesize photographer;
#synthesize title;
#synthesize license;
+ (pictureData*)picDataWith:(NSDictionary *)dictionary {
pictureData *tmp = [[[pictureData alloc] init] autorelease];
tmp.fileName = [dictionary objectForKey:#"fileName"];
tmp.photographer = [dictionary objectForKey:#"photographer"];
tmp.title = [dictionary objectForKey:#"title"];
tmp.license = [dictionary objectForKey:#"license"];
return tmp;
}
-(void)dealloc {
[fileName release];
[photographer release];
[title release];
[license release];
}
#end
I then set up these objects in an array, like so:
NSString *path = [[NSBundle mainBundle] pathForResource:#"pictureLicenses" ofType:#"plist"];
NSArray *tmpDataSource = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *tmp = [[NSMutableArray alloc] init];
self.dataSource = tmp;
[tmp release];
for (NSDictionary *dict in tmpDataSource) {
pictureData *pic = [pictureData picDataWith:dict];
NSLog(#"%#", pic.title);
[self.dataSource addObject:pic];
}
Everything works smashingly. I have a table view which loads the proper picture images, and information, no problem. Upon running Instruments for leaks, I see that my pictureData object is leaks with every allocation.
I would assume that with having my object autoreleased I would not have to worry about manually allocating and deallocating them.
Perhaps is my issue that I use autorelease, which the autoReleasePool keeps a retain count of +1 and then when I add a pictureData object to my array, that also retains it? Thank you all for your time!
edit: Don't forget to call super! Thank you Sam!
Change dealloc to:
-(void)dealloc {
[fileName release];
[photographer release];
[title release];
[license release];
[super dealloc];
}
(call [super dealloc])
In your function, change the return value to include autorelease, like
+ (pictureData*)picDataWith:(NSDictionary *)dictionary
{
...
...
return [tmp autorelease];
}
When you add pictureData object to dataSource, you increase the retain count, so you should autorelease it while returning.
Hope it helps.
I'm getting a memory leak with instruments in a class that I've created. This is the class:
.h
#import <Foundation/Foundation.h>
#interface RDItem : NSObject {
}
#property int Id;
#property (nonatomic, retain) NSString *nombre;
#property (nonatomic, retain) NSString *thumbnail;
#property (nonatomic, retain) NSString *thumbnailPush;
#property int defaultColorId;
#property int idTema;
#property (nonatomic, retain) NSString *selectedFrame;
#property (nonatomic, retain) NSString *mergedFrame;
#property (nonatomic, retain) NSMutableArray *colors;
#property (nonatomic, retain) NSMutableArray *textures;
#property (nonatomic, retain) NSMutableArray *styles;
-(void)initialize;
#end
.m
#import "RDItem.h"
#implementation RDItem
#synthesize Id;
#synthesize nombre;
#synthesize thumbnail;
#synthesize thumbnailPush;
#synthesize defaultColorId;
#synthesize idTema;
#synthesize selectedFrame;
#synthesize mergedFrame;
#synthesize colors;
#synthesize textures;
#synthesize styles;
-(void)initialize
{
colors = [[NSMutableArray alloc] init];
textures = [[NSMutableArray alloc] init];
styles = [[NSMutableArray alloc] init];
}
-(void)dealloc
{
[colors release];
[textures release];
[styles release];
}
#end
This class have 3 NSMutableArray where I'll store data. In order to prepare and initialice this class, I've developed the method initialize where the 3 arrays are created. In dealloc are released.
The leaks tool detects a leak each time this class is used because the initialize method.
Which is the best way to initialize these arrays?
Thanks.
EDIT
Hi I've solved the leak with RDItem but now appears another lear in a very similar class:
.h
#import <Foundation/Foundation.h>
#interface RDTema : NSObject {
}
#property int Id;
#property (nonatomic, retain) NSString *idManifest;
#property (nonatomic, retain) NSString *idTema;
#property (nonatomic, retain) NSString *nombre;
#property (nonatomic, retain) NSString *thumbnail;
#property (nonatomic, retain) NSString *thumbnailPush;
#property (nonatomic, retain) NSMutableArray *items;
#property (nonatomic, retain) NSMutableArray *colors;
#property (nonatomic, retain) NSMutableArray *textures;
#property (nonatomic, retain) NSMutableArray *styles;
-(void)initialize;
#end
.m
#import "RDTema.h"
#implementation RDTema
#synthesize Id;
#synthesize idManifest;
#synthesize idTema;
#synthesize nombre;
#synthesize thumbnail;
#synthesize thumbnailPush;
#synthesize items;
#synthesize colors;
#synthesize textures;
#synthesize styles;
-(void)initialize
{
/*
self.items = [[NSMutableArray alloc] init];
self.colors = [[NSMutableArray alloc] init];
self.textures = [[NSMutableArray alloc] init];
self.styles = [[NSMutableArray alloc] init];
*/
self.items = [NSMutableArray array];
self.colors = [NSMutableArray array];
self.textures = [NSMutableArray array];
self.styles = [NSMutableArray array];
}
-(void)dealloc
{
[idManifest release];
[idTema release];
[nombre release];
[thumbnail release];
[thumbnailPush release];
[items release];
[colors release];
[textures release];
[styles release];
[super dealloc];
}
Now I'm getting a leak in these lines:
self.items = [NSMutableArray array];
self.colors = [NSMutableArray array];
self.textures = [NSMutableArray array];
self.styles = [NSMutableArray array];
Anyone can explain why is happening in this class and not in RDItem class now? Are the same :(
Thanks.
This is a better suggested implementation
-(void)initialize
{
self.colors = [NSMutableArray array];
self.textures = [NSMutableArray array];
self.styles = [NSMutableArray array];
}
-(void)dealloc
{
self.colors = nil;
self.textures = nil;
self.styles = nil;
}
I think that you are getting the leak because you call your initialize message more than once and you are not releasing the variables.
Normally, you should use setters or getters to access your ivars, so the appropiate operations are called (like the release message before assigning a new value on setter).
And remember to call [super dealloc] as the last instruction for your dealloc ;)
Without seeing the code where you are initialising the RDItem i can't say for sure.
But i expect that you are not releasing your previous RDItem before creating your new one. So post the code where you are creating your RDItems so we can say for sure
I think, that leak are in arrays filling code, not init. For example, you alloc and init some NSString and put it in your NSMutable array without release or autorelease it. Or something like this. Make shure that you filling your arrays right way.
Just init them when you need it. Calling alloc and init holds to arrays whose content is nil. Call alloc initWithObjects: and fill the arrays.
I am trying to build a Grouped Sectioned View. I want to set an array as an object in the dictionary but I came across the empty array Issues.
Is this Even possible????? Is There a trick ????
#import "RootViewController.h"
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Get the specific Node for this row.
Nodes *nodes = (Nodes *)[nodesMArray objectAtIndex:indexPath.row];
// Create the Details View Controller and initialize it.
nodesDetailView *viewController = [[nodesDetailView alloc] initWithStyle:UITableViewStyleGrouped ];
[[self navigationController] pushViewController:viewController animated:YES];
// Set the title of the view to the nodes name
viewController.title = [nodes computer_name];
//Information
//Network Data
viewController.ipaddress= [nodes ipaddress];
viewController.subnet_mask= [nodes subnet_mask];
viewController.gateway= [nodes gateway];
viewController.domain_name= [nodes domain_name];
}
#import "nodesDetailViewController. h
#interface nodesDetailView : UITableViewController{
//Network Data
NSString *ipaddress;
NSString *subnet_mask;
NSString *gateway;
NSString *domain_name;
//Grouped
NSMutableArray *Keys;
NSMutableDictionary *Contents;
}
#property (nonatomic, retain) NSMutableArray *Keys;
#property (nonatomic, retain) NSMutableDictionary *Contents;
#property (nonatomic, retain) NSString *ipaddress;
#property (nonatomic, retain) NSString *subnet_mask;
#property (nonatomic, retain) NSString *gateway;
#property (nonatomic, retain) NSString *domain_name;
#end
#import "nodesDetailViewController. m
#synthesize .......
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *network = #"Network Data";
NSString *product = #"Product Details";
//IS THIS POSSIBLE ??????? Because I get An Empty array
[contents setObject:[NSArray arrayWithObjects: ipaddress,subnet_mask, gateway, domain_name, nil] forKey:network];
return self;
}
Thank You In Advance.
All of those strings that you are adding to the array haven't even been allocated/initialized yet. That's why the array is empty. You can't just go: NSString *emptyString; and then go: [myArray addObject:emptyString];. Your strings are all empty.
Check the values u are passing from the table view. They maybe nil. I just used this much of data and i m getting correct NSLog.
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *my = #"kk";
NSString *my1 = #"polko";
[contents setObject:[NSArray arrayWithObjects: my1,my, nil] forKey:#"o"];
NSLog(#"%#" , contents);
For Those Who are wondering: Problem Solved My code was fine. the problem was :
it was in the wrong place.
The Code Supposed to be in - (void)viewDidLoad and not in - (id)initWithStyle:
I want to thank everybody who took the time to look in to it.
I have no idea why i put the code there to begin with.
Thanx Again
I'm getting a leak from using substringWithRange as shown in the line of code below. I though all these functions were Autorelease and you didnt need to alloc/release them manually.
NSCFString is the object being leaked.
What is it I am doing wrong?
aLTR.drew = [substring substringWithRange:NSMakeRange(match.location+1, (match2.location-(match.location+1)))];
What I am trying to do is extract a substring and store it into my storage class. Code for that below.
#import <Foundation/Foundation.h>
#interface LeagueTableRow : NSObject
{
NSString *_teamName;
NSString *_played;
NSString *_won;
NSString *_drew;
NSString *_lost;
NSString *_goalsFor;
NSString *_goalsAgainst;
NSString *_points;
}
#property(nonatomic, copy) NSString *teamName;
#property(nonatomic, copy) NSString *played;
#property(nonatomic, copy) NSString *won;
#property(nonatomic, copy) NSString *drew;
#property(nonatomic, copy) NSString *lost;
#property(nonatomic, copy) NSString *goalsFor;
#property(nonatomic, copy) NSString *goalsAgainst;
#property(nonatomic, copy) NSString *points;
-(id)init;
#end
#import "LeagueTableRow.h"
#implementation LeagueTableRow
#synthesize teamName = _teamName;
#synthesize played = _played;
#synthesize won = _won;
#synthesize drew = _drew;
#synthesize lost = _lost;
#synthesize goalsFor = _goalsFor;
#synthesize goalsAgainst = _goalsAgainst;
#synthesize points = _points;
-(id)init
{
self = [super init];
return self;
}
-(void) dealloc
{
self.teamName = nil;
self.played = nil;
self.won = nil;
self.drew = nil;
self.lost = nil;
self.goalsFor = nil;
self.goalsAgainst = nil;
self.points = nil;
[super dealloc];
}
#end
I'm quiet surprised I got some leaks I though I was managing the memory quiet tidily.
Thanks for the advice and tips.
-Code
In your dealloc, simply release all the string ivars:
[_teamName release];
etc...
Alternatively, you could do:
[self.teamName release];
etc...
I prefer to use the ivars directly, in such situations.