0

I'm learning Objective-C and have some trouble with adding objects to an NSMutableArray. I have a class called Song and a class called Playlist. I need to add Songs to a Playlist. Here is the Playlist.h file (the array is called mySongs:

#import <Foundation/Foundation.h>

@interface Playlist : NSObject

@property(nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSMutableArray *mySongs;

-(instancetype)initPlaylistWithName: (NSString *)playlistName;
-(instancetype)init;

-(void)addSong: (Song *)theSong;
-(void)removeSong: (Song *)theSong;
-(void)printSongsInPlaylist;

@end

In Playlist.m file I have a method, which checks that the playlist doesn't contain the song, and if so, adds it to the array. It looks like this:

-(void)addSong:(Song *)theSong {
for(Song * song in mySongs){
    range = [song.title rangeOfString:theSong.title];
    if(range.location != NSNotFound)
        return;

}

[mySongs addObjects:theSong];
}

I also have a method, which prints all the songs inside a particular playlist. Here how it looks like:

 -(void)printSongsInPlaylist {
if ([mySongs count] != 0) {
for (Song *song in mySongs) {
    NSLog(@"Title: %@, Artist: %@, Album: %@, PlayingTime: %@", song.title, song.artist, song.album, song.playingTime);
}
} else {
    NSLog(@"No songs");
}

The problem is, this method always prints "No songs", which means, the count of the array is 0. This happens even if in main.m file I call the method for adding a song to the playlist first.

I know there is some simple mistake but I can't figure out what it is. I've also checked other answers to similar questions here, but they didn't help me.

If you could help me understand why I can't add an object to the array, I would appreciate it.

2
  • 2
    Have you alloc init-ed your mySongs array? If you are new to ObjC programming, this might be useful to you stackoverflow.com/a/11770303/3883492 Commented Jan 23, 2018 at 15:19
  • @dvp.petrov, thank you! I've indeed forgotten to alloc and init it. I've, also, tried the way that is mentioned in the link, but it seems that alloc init -ing it that way doesn't work when I call the array from the implementation of the class. Maybe, it is useful when you call the array not from inside of the class in which it is defined? Commented Jan 23, 2018 at 15:29

2 Answers 2

2

This is how you can lazy init your mutable array. What this does is: alloc initing your array the first time you need it. It is a pretty common practice for static arrays with predefined values, that do not need to be loaded in the memory prior some event.

- (NSMutableArray*)mySongs
{
    if (!_mySongs) {
        _mySongs = [[NSMutableArray alloc] init];
    }
    return _mySongs;
}

What is more: The check you are making in addSong method is fine, but I would recommend overriding the isEqual method of Song class.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, for the explanation. Now I get it. Could you, also, explain why you prefer using isEqual ?
Lazy initialization is tempting, but both a waste of time and oft a source of debugging pain. It is also a serious hindrance to performance optimization.
@bbum could you provide any literature explaining your arguments. I will gladly read that
@TigranIskandaryan more often than not, some comparing criteria is applied on several places in your code. For instance, you might need to select some song or remove from the array. And the idea of comparing whole objects by some of their arguments (per title in your case) is commonly used practice. You can read more on the subject here. Benefit from this: you can use [mySongs containsObject: song]
@dvp.petrov See my comments on stackoverflow.com/questions/21764666/…. I should probably go and add an answer to one of the "when to use lazy initialization" questions and expand on it a bit.
1
 -(instancetype)initPlaylistWithName: (NSString *)playlistName;
{

    self = [super init];

    if(self)
    {
        _name = playlistName

        _mySongs = [NSMutableArray new];

    }

   return self;

}

3 Comments

Yeah, it works, I have forgotten to alloc init it. Thanks!
you'll need more code that that... the super call, self check, and return, for example.
@bbum you're right but i meant to highlight main reason of the problem sure self must returned

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.