NSMutable Array returning NULL when NSLog - objective-c

So I have an NSMutable array that I populate in viewDidLoad and then I NSLog it and it returns NULL in the console... I have looked around on stack-overflow and the apple reference and cannot find a solution to my problem.
Heres the code I used:
//Populate array
-(void)populateArray{
[TextArray addObject:#"Text1"];
[TextArray addObject:#"Text2"];
[TextArray addObject:#"Text3"];
[TextArray addObject:#"Text4"];
[TextArray addObject:#"Text5"];
NSLog(#"%#",TextArray);
NSLog(#"%#",[TextArray objectAtIndex:1]);
}
-(void)viewDidLoad
{
TextArray = [[NSMutableArray alloc] init];
[self populateArray];
}
And in the .h file
NSMutableArray *TextArray;
Thanks in advanced!
~Matt

the code you posted does not contain enough information for us to provide a specific answer. chances are, the methods are not being called in the order you expect them (e.g. populateArray is called from another point before viewDidLoad).
some assertions should help diagnose this:
//Populate array
-(void)populateArray
{
assert(nil != self.textArray && "you need to create an array");
[self.textArray addObject:#"Text1"];
[self.textArray addObject:#"Text2"];
[self.textArray addObject:#"Text3"];
[self.textArray addObject:#"Text4"];
[self.textArray addObject:#"Text5"];
assert(5 == [self.textArray count] && "populateArray has been called twice or serious threading error");
NSLog(#"%#",textArray);
NSLog(#"%#",[textArray objectAtIndex:1]);
}
-(void)viewDidLoad
{
assert(nil == self.textArray && "you need to clear your array (e.g. in viewDidUnload) or check if it has already been populated");
self.textArray = [NSMutableArray array];
[self populateArray];
assert(5 == [self.textArray count] && "populateArray has been called twice or serious threading error");
}
lastly, if this array never changes, it's going to be much simpler to create this in your initializer rather than lazily. such an array will not require much memory, in case that was your concern.
Update the construct takes this form:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
{
self = [super initWithNibName:nibName bundle:nibBundle];
if (nil != self){
textArray = [[NSArray alloc] initWithObjects:#"Text1", #"Text2", #"Text3", #"Text4", #"Text5", nil];
// ...
}
return self;
}
lastly, viewDidLoad may be certainly be called multiple times on the same instance. the system unloads (then lazily reloads) views in low memory conditions.

Related

How can I have array stored inside of array in Objective C?

My issue is, I have an exercise that asks to create 3 classes:
Song(to create and set songs)
Playlist(to create and add songs to it)
MusicCollection(to have a collection of playlists) now this class is tricky, I need to have a master library playlist in the playlists collection that will contain every song in the collection...
So, from what I saw some people define in the MusicCollection property of type Playlist that called library, and in the initialization they do:
-(id) initWithName: (NSString *) theName
{
self = [super init];
if (self) {
musicCollection = [[NSMutableArray alloc] init];
library = [[Playlist alloc] initWithName: #"library"];
[musicCollection addObject: library];
}
return self;
}
From what I understand from this, everytime user initialize a collection, so a playlist object will be added to the collection array...
And the problem is that in the addPlaylist method to a collection, they did not add this playlist songs to the library...like this:
-(void) addPlaylist: (Playlist *) thePlaylist
{
if ([musicCollection containsObject: thePlaylist] == NO)
[musicCollection addObject: thePlaylist];
}
Any thoughts? im really stuck with this :/
I though maybe having the library to by an array inside the collection array and iterate through it to look if the songs are in the library, and if not to add them..
Now, in the Playlist.m the addsong method is:
-(void) addSong:(Song *)theSong
{
[playList addObject:theSong];
}
but I see that in the MusicCollection.m they added a method to add songs that adding songs to the library:
-(void) addSong: (Song *) theSong toPlaylist: (PlayList *) thePlaylist
{
if([thePlaylist.playList containsObject:theSong]==NO)
[thePlaylist addSong:theSong];
if([library.playList containsObject:theSong]==NO)
[library addSong:theSong];
}
But what if i create a Playlist and just add it to a MusicCllection? without adding songs through the MusicCollection method to add songs..
For object comparison to work
-(void) addPlaylist: (Playlist *) thePlaylist
{
if ([musicCollection containsObject: thePlaylist] == NO)
[musicCollection addObject: thePlaylist];
}
you must override isEqual: method in PlayList
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToPlayList:other];
}
//Assuming playListId is an unique identifier in `PlayList`
- (BOOL)isEqualToPlayList:(PlayList*)playList{
if (self == playList)
return YES;
if (self.playListId != playList.playListId)
return NO;
//If you you a combinational uniqueness, check for them as well
return YES;
}
For more info follow the object comparison in following link

Is it ok to retain and autorelease at the same time?

I have the following code:
#interface MyClass : NSObject
{
NSMutableArray *items;
}
#end
#implementation MyClass
-(Item *)getItem
{
if(items.count < 1)
{
[self buildItemsArray];
}
Item *item = [[[items objectAtIndex:0]retain]autorelease];
[items removeObjectAtIndex:0];
return item;
}
-(void)buildItemsArray
{
// ...
[items addItem:someNewItem];
[items addItem:someOtherNewItem];
}
#end
I have a function that returns an item. If the items go down to 0, then the items array is built again inside buildItemsArray. My game logic requires that when I return an item, I need to remove it from the array. So, I am using a retain to ensure that the item is valid till the return line (since the only other known retain happened when the item was added to the items array), and an autorelease to ensure it gets cleaned up later. I have checked that this code neither crashes nor leaks. I wonder if:
a) This is OK - the reason I ask is that I have predominantly seen code with alloc/init/autorelease, and haven't run into this case with retain/autorelease
b) Is there some reason to alloc/init/autorelease instead:
Item *item = [[Item alloc]initWithItem:[items objectAtIndex:0]autorelease];
Thanks
This is generally ok:
Item *item = [[[items objectAtIndex:0] retain] autorelease];
[items removeObjectAtIndex:0];
return item;
Though this would make the intent clearer (returning an autoreleased object):
Item *item = [[items objectAtIndex:0] retain];
[items removeObject:item];
return [item autorelease];
No reason to alloc/init. That just adds unnecessary overhead.
Like I said in my comment, if this is a (relatively) new project, you really really really should be using ARC and not worry about these things anymore.

Freshly init array is empty - why?

Newbie here (to C, objective-C, and iOS)...
For this code in my AppDelegate.m, why is the freshly initialized array empty? Looks to me like I give it some values. Clue1 etc are are series of UILabels and there are no issues noted by Xcode. I've been through SO quite a bit and this seems to be the way to do it. Xcode 4.2. Thanks!
- (id)init {
self = [super init];
if(self) {
// Make arrays containing the objects: this is the objective-C way!
self.clueLabs = [[NSMutableArray alloc] initWithObjects: Clue1, Clue2, Clue3, nil];
}
NSLog(#"%#", [clueLabs description]);
if (!clueLabs || ![clueLabs count]) { // these 2 do m/l the same thing
NSLog(#"clueLabs is empty!");
}
return self;
}
Check if Clue1, Clue2 Clue3 are not nils.

Weird Memory Management Occurrence iOS

For some reason in my below code, the replies array is NSLogging the correct description, but the comment.replies array is NSLogging null.
I immediately presumed that this was due to a memory management issue within my code, but I don't believe that that is true.
Please can you tell me why this is occurring?
- (TBComment *) dictionaryToComment:(NSDictionary *)dict {
TBComment *comment = [[TBComment alloc] init];
[comment setBody:[dict objectForKey:#"body"]];
[comment setCommentID:[dict objectForKey:#"id"]];
[comment setCreated_at:[dict objectForKey:#"created_at"]];
[comment setUpdated_at:[dict objectForKey:#"updated_at"]];
[comment setUser:[self dictionaryToUser:[dict objectForKey:#"user"]]];
NSMutableArray *replies = nil;
if ([[dict allKeys] containsObject:#"replies"]) {
replies = [[NSMutableArray alloc] init];
for (NSDictionary *reply in [dict objectForKey:#"replies"]) {
NSLog(#"in");
[replies addObject:[self dictionaryToComment:reply]];
}
}
if (replies != nil) {
[comment setReplies:replies];
NSLog(#"COMMENT REPLIES = %#", comment.replies);
NSLog(#"REPLIES = %#", replies);
[replies release];
}
return [comment autorelease];
}
Console ->
2011-11-30 21:25:14.980 Timbrr[2379:f803] in
2011-11-30 21:25:14.980 Timbrr[2379:f803] COMMENT REPLIES = (null)
2011-11-30 21:25:14.980 Timbrr[2379:f803] REPLIES = (
"<TBComment: 0x68dbeb0>"
)
- (void) setReplies:(NSArray *)_replies {
hasReplies = (_replies == nil ? NO : ([_replies count] == 0 ? NO : YES));
//replies is synthesised
}
After seeing your implementation of setReplies:, I don't think you quite understand how #synthesize works.
#synthesize replies; will generate a getter and a setter for this instance variable. BUT since you're overriding it (and improperly) the synthesized setter is being tossed aside. (In fact, no setter is being created for you at all, since you wrote one yourself.)
The root issue is that in your implementation of setReplies:, you're not actually assigning the value of your replies instance variable to the parameter of the setter.
What I think you want is:
- (void) setReplies:(NSArray *)_replies {
hasReplies = (_replies == nil ? NO : ([_replies count] == 0 ? NO : YES));
// How is your ivar defined in the header file? As _replies, or replies?
if (replies != _replies) {
[replies release];
replies = [_replies retain];
}
}
I would suspect that either comment is nil (though this would require explicit nil-returning code in TBComment, which is possible, but unusual), or that -replies or -setReplies: are incorrectly implemented. Do you have custom implementations for those?
Your implementation of setReplies: never sets _replies.
The replies property is never set - when you define setReplies:, the #synthesize directive does not create any setter method.

Retrieving Class Object from NSArray and adding to self

Hi im trying to retrieve an object of a specific class from an NSMutableArray, and then add it to self: eg:
- (void) init{
_Objects = [[NSMutableArray alloc]init];
Psychicing *psy = [[Psychicing alloc]init];
[psy startPsychic];
[_Objects addObject: psy];
[psy release];
}
This creates an object of class Psychicing, then runs the [psy startPsychic] method to create the internals of the class object. Then I add the psy object to _Objects NSMutableArray.
-(void)startPsychic{
id psychicParticle = [CCParticleSystemQuad ......]; //is Synthesised with (assign)
//Other things are set here such as position, gravity, speed etc...
}
When a touch is detected on screen, I want to take the psy object from the _Objects array and add it to self: Something like this (Although this gives runtime error)
-(void) Touches.....{
for (Psychicing *psy in _Objects){
[self addChild: psy.psychicParticle];
}
}
I hope i have explained it clearly enough, if you need more clarification let me know.
So basically:
[MainClass Init] -> [Psychicing startPsychic] -> [MainClass add to array] -> [MainClass add to self]
I'm assuming the _Objects (which should be a lowercase o to follow conventions) is storing objects other than the Psychicing object and you're trying to pull just the Psychicing object out of it in the -(void)Touches... method (which also should be lowercase). If so, you could do:
for (id obj in _Objects)
{
if ([obj isMemberOfClass:[Psychicing class]])
[self addChild:obj.psychicParticle];
}
That will cause only the Psychicing objects in the array to be added as a child to self.
It looks like you do have another error though if the code you pasted in is your real code. Init should be defined as:
- (void) init{
_Objects = [[NSMutableArray alloc]init];
Psychicing *psy = [[Psychicing alloc]init];
[psy startPsychic];
[_Objects addObject: psy];
[psy release];
}
with _Objects defined as an instance variable (or property) in the class's interface. As you wrote it, it's a method variable in the init method and is leaking. So when you try to access _Objects in -touches, _Objects is most likely nil.
Okay, with the help of McCygnus I got it working, the only thing missing with a pointer to the id object:
for (id obj in _Objects){
if ([obj isMemberOfClass:[Psychicing class]]){
Psychicing *apsy = obj;
[apsy.psychicParticle setPosition:location];
[self addChild:apsy.psychicParticle];
}
}