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.

Tigran Iskandaryan
  • 1,371
  • 2
  • 14
  • 41
  • 2
    Have you `alloc init-ed` your `mySongs` array? If you are new to ObjC programming, this might be useful to you https://stackoverflow.com/a/11770303/3883492 – dvp.petrov Jan 23 '18 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? – Tigran Iskandaryan Jan 23 '18 at 15:29

2 Answers2

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.

dvp.petrov
  • 1,110
  • 13
  • 20
  • Thanks, for the explanation. Now I get it. Could you, also, explain why you prefer using `isEqual` ? – Tigran Iskandaryan Jan 23 '18 at 15:48
  • 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 Jan 23 '18 at 17:07
  • @bbum could you provide any literature explaining your arguments. I will gladly read that – dvp.petrov Jan 23 '18 at 17:17
  • @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](http://nshipster.com/equality/). Benefit from this: you can use `[mySongs containsObject: song]` – dvp.petrov Jan 23 '18 at 17:25
  • @dvp.petrov See my comments on https://stackoverflow.com/questions/21764666/why-do-the-courses-at-stanford-use-the-lazy-initialisation. I should probably go and add an answer to one of the "when to use lazy initialization" questions and expand on it a bit. – bbum Jan 23 '18 at 18:16
1
 -(instancetype)initPlaylistWithName: (NSString *)playlistName;
{

    self = [super init];

    if(self)
    {
        _name = playlistName

        _mySongs = [NSMutableArray new];

    }

   return self;

}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87