Variable is not a CFString - iphone

I am getting value from JSON it gives exception var is not CFString.
below is the link from which i am getting data
http://www.krsconnect.no/community/api.html?method=categories&appid=620&mainonly=true
NSString *test = aBook.catId;
Book Class
#interface Book : NSObject {
NSString *catId;
NSString *name;
}
#property(nonatomic,retain)NSString*catId;
#property(nonatomic,retain) NSString *name;
#end
#import "Book.h"
#implementation Book
#synthesize catId,name;
-(id)init{
self=[super init];
}
- (id)initWithDictionary:(NSDictionary*) dict {
self.catId = [dict valueForKey:#"categoryId"];
self.name = [dict valueForKey:#"name"];
return self;
}
- (void)dealloc {
[catId release];
[name release];
[super dealloc];
}
#end

Its an integer maybe. Use this.
NSString* test = [NSString stringWithFormat:#"%d",aBook.catId];

I think this question should help you
Replace multiple characters in a string in Objective-C?
CFStringRef aCFString = (CFStringRef)aNSString;
works perfectly and transparently. Likewise:
NSString *aNSString = (NSString *)aCFString;

Related

Dealloc of custom object

I have this Class in my project :
#interface VideoItem : NSObject <NSCoding> {
NSString *name;
NSString *artist;
int seconds;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *imgUrl;
#property (nonatomic, retain) NSString *artist;
#end
And this is how i create this object:
VideoItem *item = [[VideoItem alloc] init];
item.name = name;
item.imgUrl = imgLink;
item.artist = artist;
And this is the dealloc:
- (void)dealloc{
[name release];
[imgUrl release];
[artist release];
[super dealloc];
}
And i want to know if this dealoc is ok with the NON-ARC? did i need to do something else because this NSString are with Property?
Edit
And if the VideoItem object was create with:
VideoItem *item = [[VideoItem alloc] init];
item.name = [NSString alloc]initWithFormat#"%#",name];
item.imgUrl = [NSString alloc]initWithFormat#"%#",imgLink];
item.artist = [NSString alloc]initWithFormat#"%#",artist];
Did in this case the dealloc is still ok? or i need to change something?
Everything looks ok, you are releasing all the #properties of your object. I would probably as well point them to nil, just to make sure, that if one of those properties is called, it will be nilled and not have a garbage value, like so:
- (void)dealloc{
[name release], name = nil;
[imgUrl release], imgUrl = nil;
[artist release], artist = nil;
[super dealloc];
}
Another thing, no related, it would be cleaner, if you would create your own init, so you can pass the properties values, when you actually create the object, like so:
-initWithName:(NSString *)name withImgURL:(NSString *)imgURL withArtist:(NSString *)artist;
Your edit:
item.name = [NSString alloc]initWithFormat#"%#",name];
item.imgUrl = [NSString alloc]initWithFormat#"%#",imgLink];
item.artist = [NSString alloc]initWithFormat#"%#",artist];
Only based on this, it will create a leak, so you should be careful. To fix this:
item.name = [[NSString alloc]initWithFormat#"%#",name] autorelease];
item.imgUrl = [[NSString alloc]initWithFormat#"%#",imgLink] autorelease];
item.artist = [[NSString alloc]initWithFormat#"%#",artist] autorelease];
If you don't have ARC enabled than your destructor is correct. You are releasing all the properties that are retained and calling super, which is all you need.

Leaky Custom Object for storing data from a plist

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.

Getting leaks from substringWithRange

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.

Objective-C error while implementing class?

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];

UITableView custom class huge leak

I am using a custom class to display some info on a table view.
The problem is that as long as I scroll the tableview memory is leaking...
I guess I have something wrong at my class.
Please have a look:
#interface Person : NSObject {
NSString *name;
NSString *surname;
NSString *address;
NSString *email;
}
#property (nonatomic, copy) NSString *name, *surname, *address, *email;
#implementation Person
#synthesize name, surname, address, email;
-(id)init {
[super init];
name = [[NSString alloc] init];
surname = [[NSString alloc] init];
address = [[NSString alloc] init];
email = [[NSString alloc] init];
return self;
}
- (void)dealloc
{
[name release];
[surname release];
[address release];
[email release];
[super dealloc];
}
#import "Person.h"
#interface Group : NSObject {
NSString *groupTitle;
NSMutableArray *persons;
}
#property (readwrite, copy) NSString *groupTitle;
- (void)addPerson:(Person *)person;
- (void)removeAll;
- (NSArray *)getPersons;
- (int)PersonsCount;
#end
#implementation Group
#synthesize groupTitle;
-(id)init {
[super init];
persons = [[NSMutableArray alloc] init];
return self;
}
-(void)addPerson:(Person *)person {
[persons addObject:person];
}
-(void)removeAll {
[persons removeAllObjects];
}
-(NSArray *) getPersons {
return [persons copy];
[persons release];
}
-(int)personsCount {
return [persons count];
}
-(void)dealloc {
[groupTitle release], groupTitle = nil;
[persons release], persons = nil;
[super dealloc];
}
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
…….
Group *groupForRow = [[Group alloc] init];
Person *personForRow = [[Person alloc] init];
personForRow = [[groupForRow getPersons] objectAtIndex:indexPath.row];
_personName = personForRow.name;
_personSurname = personForRow.surname;
_personAddress = personForRow.address;
_personEmail = personForRow.email;
[groupForRow release], groupForRow = nil;
[personForRow release], personForRow = nil;
…..
return cell
Few corrections (read the comments):
#interface Person : NSObject {
NSString *name;
NSString *surname;
NSString *address;
NSString *email;
}
// copy is OK for strings...
#property (nonatomic, copy) NSString *name, *surname, *address, *email;
#end
#implementation Person
#synthesize name, surname, address, email;
- (id)init {
if (self = [super init]) {
// There is no need to allocate the strings
// In addition, once you write 'name = [[NSStrin alloc] init];' you don't use the property.
// If you do want to use the property setter then you should write 'self.name = #"some string";'
}
return self;
}
- (void)dealloc {
[name release];
[surname release];
[address release];
[email release];
[super dealloc];
}
#end
#import "Person.h"
#interface Group : NSObject {
NSString *groupTitle;
NSMutableArray *persons;
}
// Any special reason for "readwrite" instead of "nonatomic"?
#property (readwrite, copy) NSString *groupTitle;
// This property is more important than the string:
#property (nonatomic, retain) NSMutableArray *persons;
- (void)addPerson:(Person *)person;
- (void)removeAll;
- (NSArray *)getPersons;
- (int)PersonsCount;
#end
#implementation Group
#synthesize groupTitle, persons;
- (id)init {
if (self = [super init]) {
// Use the autoreleased array instance ([NSMutableArray array]) and set it to the property setter that will retain the object:
self.persons = [NSMutableArray array];
}
return self;
}
- (void)addPerson:(Person *)person {
// I prefer using properties (the "self." in the beginning) instead of the members directly...
[self.persons addObject:person];
}
- (void)removeAll {
[self.persons removeAllObjects];
}
// I think that this getter is unnecessary - use the property instead...
- (NSArray *) getPersons {
// There is no need to copy
return [persons copy];
// Don't you have a warning for this line? It is never executed
[persons release];
}
- (int)personsCount {
return [self.persons count];
}
- (void)dealloc {
[groupTitle release], groupTitle = nil;// The "groupTitle = nil" is unnecessary.
[persons release], persons = nil;// The "persons = nil" is unnecessary.
[super dealloc];
}
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
…….
Group *groupForRow = [[Group alloc] init];// Do you REALLY have to allocate this object each "cellForRowAtIndexPath"??
Person *personForRow = [[Person alloc] init];// Get rid of the "= [[Person alloc] init]" - this is a leak (because of the next line)
personForRow = [[groupForRow getPersons] objectAtIndex:indexPath.row];// If you will use the property persons instead of the "getPersons" (that copies the array) then you will get rid of another leak
// What are these?
_personName = personForRow.name;
_personSurname = personForRow.surname;
_personAddress = personForRow.address;
_personEmail = personForRow.email;
// The " = nil" is unnecessary here...
[groupForRow release], groupForRow = nil;// If you won't allocate the group then you won't need this line...
[personForRow release], personForRow = nil;// NSZombie - you release object that you don't owe (do you have crashes, that you don't know why they are happen?)
…..
return cell;
}
There is a lot wrong here, please delve a little into objective-C to get a grasp of the use of #property and #synthesize to get correctly functioning getter/setter methods.
As for your memory leak when scrolling, it is caused by the allocs in cellForRowAtIndexPath which are not balanced by either a release or an autorelease.
This:
Group *groupForRow = [[[Group alloc] init] autorelease];
Person *personForRow = [[[Person alloc] init] autorelease];
should fix most of your leaks. Browse around on SO for more info.