3

Firstly, I am new with Objective C.

I have my class Song that has a pair of attributes. In my main class i got a variable allSongs that is a NSMutableArray and in this array have I added all my song-objects. My problem comes when trying to call [self.allSongs removeObject:OBJECT]; Using the debugger, I can see that before the call, the list looks as expected. But after the call it will result that the targeted object will be removed but also the first element in the array will turn to nil. Is this a common pointer problem or what?

Here is my code:

in h file

@property (nonatomic, strong) NSMutableArray *songs;
@property (nonatomic, strong) NSMutableArray *allChapters;

in m file

- (void)viewDidLoad
{

self.chosenChapter = [[NSString alloc]initWithFormat:self.chosenChapter];
self.allChapters = [[NSMutableArray alloc]init];

//Chapter names and chapter page range
chapters = [[NSArray alloc]initWithObjects:@"chapter1", @"chapter2", @"chapter3", nil];
chaptersRange = [[NSArray alloc]initWithObjects:@"25", @"51", @"88", nil];
//Filnames of every song
files = [[NSMutableArray alloc] initWithObjects:@"test", @"Feta_fransyskor", nil];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: @"page" ascending: YES];
self.songs = [[NSMutableArray alloc]init];

for(int i = 0; i < chapters.count; i++){
    Song *chapter = [[Song alloc]init];
    [chapter setPage:(NSString *)self.chaptersRange[i]];
    [chapter setTitle:(NSString *)self.chapters[i]];
    [self.allChapters addObject:chapter];
    [self.songs addObject:chapter];
}

NSString *filePath;
int i;
for (i = 0; i < files.count; i++) {
    filePath = [[NSBundle mainBundle] pathForResource:files[i] ofType:@"txt"];
    if(filePath){
        NSError *error;
        NSString *textFromfile = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error: &error];
        /*
         index
         0 for page number
         1 for title name
         2 for melody name
         3 -> for lyrics
         */

        NSMutableArray *newLineseparatedText = (NSMutableArray *)[textFromfile componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

        if(newLineseparatedText){
            Song *newSong = [[Song alloc]init];
            [newSong setPage:newLineseparatedText[0]];
            [newSong setTitle:newLineseparatedText[1]];
            [newSong setMelody:newLineseparatedText[2]];

            [newLineseparatedText removeObjectAtIndex:0]; //remove page number
            [newLineseparatedText removeObjectAtIndex:0]; //remove title name
            [newLineseparatedText removeObjectAtIndex:0]; //remove melody name

            [newSong setLyric:[newLineseparatedText componentsJoinedByString:@"\n"]];

            [songs addObject:newSong];
        }
    }
}

[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

[super viewDidLoad];


}

-(void)addChapters{
for(int i = 0; i < self.allChapters.count; i++){
    if([self.songs containsObject:self.allChapters[i]] == false)
        [self.songs addObject:self.allChapters[i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: @"page" ascending: YES];
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

}

-(void)addChapters{
for(int i = 0; i < self.allChapters.count; i++){
    if([self.songs containsObject:self.allChapters[i]] == false)
        [self.songs addObject:self.allChapters[i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: @"page" ascending: YES];
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

}

-(void)removeChaptersExcept:(Song *) chapter{
for(int i = 0; i < self.allChapters.count; i++){
    if(self.allChapters[i] != chapter && [self.songs containsObject:self.allChapters[i]])
        [self.songs removeObject:self.allChapters[i]];
}

}

last line of this code is were i get an error, as the mutableArray has a couple of nil elements.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.chosenChapter isEqualToString:@"Alla"]){
    [self addChapters];
}
else{
    Song *chapter = nil;
    for(int i = 0; i < self.allChapters.count; i++){
        if([((Song *)self.allChapters[i]).title isEqualToString:self.chosenChapter]){
            chapter = self.allChapters[i];
            break;
        }

    }
    [self addChapters];
    [self removeChaptersExcept:chapter];
}




NSString *cellIdentifier = nil;
UITableViewCell *cell = nil;

NSString *page = ((Song *)self.songs[indexPath.row]).page;

and here are some screen bumps

This is before removing first object

enter image description here

This is after the first object was removed. You see how one element disapeared as expected and the other is set too nil?

enter image description here

9
  • 1
    you should allocate your allChapters mutable array too. self.allChapters = [NSMutableArray alloc] init]; and ditto with self.songs variable After allocating the array you may call addObject on it. Also, its better to access all instance variables using self Commented Mar 17, 2013 at 12:33
  • Why is better to access all instance variables using self? Commented Mar 17, 2013 at 12:39
  • I forgot to add that, i am actualy allocating my MutableArrays in the beginning of the did load method Commented Mar 17, 2013 at 12:40
  • 1
    How did you determine your array has nil elements in it? (and to be clear, you're talking about self.songs in the removeChaptersExcept: method, right?) I find that to be quite unlikely as inserting nil into a collection crashes with an bad argument exception. Commented Mar 17, 2013 at 13:48
  • 2
    It's impossible for an NSMutableArray to contain nil. Something else is happening. Commented Mar 17, 2013 at 14:06

1 Answer 1

2

Sometimes the Variables View shows incorrect values. An array can't contain nil values, so this is definitely a case where the values are wrong. You state that your application crashes on this line:

NSString *page = ((Song *)self.songs[indexPath.row]).page;

My guess is that self.songs[indexPath.row] simply doesn't have a property called page. Try to replace this line with this code:

Song *s = self.songs[indexPath.row];
if (s == nil)
{
    NSLog("Song is nil! How can that be?");
}
else
{
    NSLog("Page is %@", s.page);
}

It will help you pin-point the problem. Good luck.

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

5 Comments

Thanks for your answer, in the image of my debugging, you can see that there a becoming some elements with id 0x000000, so nil? This happends with three elements in the end. So yes self.songs[indexPath.row] is equal to nil.
I still don't understand how that nil gets there after my removeObject call.
Are saying that just based on the values you see in the image you attached? If so, then please note that I wrote in my answer that sometimes you see wrong values in that variables view. Please try my code and check if it enters the "s == nil" condition.
you were right that the debugger showed the wrong values. The array actually have correct values. This means i only have some index problem in my code that I will find soon enough. I will start using NSLog more often by now.
Thanks alot, i've been struggling with this some time now.

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.