1

To start let me tell you I am a total Objective-C beginner. This is my problem:

I have a NSMutableArray that stores objects, (Player) that has the name of the player and his/her score.

I am able to add objects to the array using addObject, but I am having trouble traversing this array. This is how I do it:

// Get the reference to the array 
NSMutableArray *myarray = [delegate getArray];
// Create a numerator
NSEnumerator *e = [myarray objectEnumerator];
id object;
while (object = [e nextObject])
{
    [object printPlayer];
}

The method printPlayer belongs to the Player class and it just prints the name and the score.

The problem is when I have three players in the array and I am trying to print the content, it reaches this error inside the printPlayer method:

Thread 1: EXC_BAD_ACCESS(code=1, address=0x0000008)

Strangely if I use NSLog(@"%@", object); instead of [object printPlayer]; it prints a reference to the object and does not reach any error.

Anyone could point me what could be the problem when I try to use [object printPlayer]

Cheers

Update 1: This is my printPlayer method:

-(void) printPlayer
{
    NSLog(@"\n\nName: %@\nScore: %d", playerName, playerScore);
}

Update 2:

Player.h:

@interface PROGPlayer : NSObject
@property (nonatomic, assign) NSString *playerName;
@property (nonatomic, assign) int playerScore;
-(id) init: (NSString *) n;
-(void) printPlayer;
@end

Player.m:

#import "PROGPlayer.h"
@implementation PROGPlayer

@synthesize playerName;
@synthesize playerScore;
/**
 * Player's class constructor
 * @param   n Player's name
 * @param   s Player's score
 */
-init: (NSString *) n
{
    if (!(self = [super init])) return nil;
    else 
    {
        playerName = n;
        playerScore = 0;
    }
    return self;
}

-(void) printPlayer
{
    NSLog(@"\n\nName: %@\nScore: %d", playerName, playerScore);
}
@end
ivantxo
  • 719
  • 5
  • 18
  • 36
  • Are you using Automatic Reference Counting in your project? – Jacob Relkin Apr 27 '12 at 00:46
  • DOES NOT ANSWER YOUR QUESTION.. BUT A GENERAL SUGGESTION http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocFastEnumeration.html – Neo Apr 27 '12 at 00:51
  • 2
    You might have an error in your printPlayer code. Can you post that? – Mike Z Apr 27 '12 at 00:54
  • Your traversal looks generally fine - considering that `player.description` works fine (`NSLog(@"%@", player);`) I would reckon that the problem lies within printPlayer, just like @MikeZ assumes. – Till Apr 27 '12 at 01:11
  • @JacobRelkin no, I am not using ARC. Why? Could it be the problem? – ivantxo Apr 27 '12 at 01:13
  • Does your code compile without any warnings? – Till Apr 27 '12 at 01:17
  • You most likely are getting deleted objects due to problems with your reference counting logic. This would be unrelated to the NS(Mutable)Array or how you iterate through it. – Hot Licks Apr 27 '12 at 01:20
  • You say you can log your object without error. I think your error is in your string format then. Try one piece at time. `NSLog(@"%@", playerName);` See if that works. If so, then try `NSLog(@"%d", playerScore);` (I'm guessing this is your issue) Let me know the results. – Mike Z Apr 27 '12 at 01:25
  • It has happened the same at some point the code reaches an error. Besides I am able to log the complete object but not pieces like the playerName or playerScore. Probably what @Hot Licks is saying is true it's something that does not have to do with NSMutableArray. – ivantxo Apr 27 '12 at 01:31
  • The object Player has a playerName attribute this is a NSString value. What is happening is that when I am looping the objects I don't know why the reference to the NSString field is being freed. There is no reference to the NSString attribute. Why is this happening? – ivantxo Apr 27 '12 at 02:06
  • Sounds like the Player object isn't retaining its playerName ivar. Do you have a setPlayerName method, or are you using a synthesized accessor for a @property? If it's a @property, what flags are set in the declaration (nonatomic, assign/retain, etc.)? Posting your Player object source would help here. – davehayden Apr 27 '12 at 02:20
  • because your vars are properties, you should use self.playerName = ..., and self.playerScore = ..., your problem might be that they're not being set properly. – C4 - Travis Apr 27 '12 at 04:37
  • @C4-Travis thanks but that's not the problem I keep losing the reference to the Player object. – ivantxo Apr 27 '12 at 04:43
  • try switching the (nonatomic, assign) to (nonatomic, strong)... – C4 - Travis Apr 27 '12 at 04:45
  • @C4-Travis it is working with strong. Why? – ivantxo Apr 27 '12 at 04:57
  • As an unrelated side note, that else inside your init is unnecessary since the if branch will return anyway. – Jarsen Apr 27 '12 at 05:00
  • strong pointers in ARC increment the retain count and force an object to stay alive until that pointer is set to null. I'd say the problem was that you weren't retaining your playerName correctly and it would get released, then you would try to use it but it was already long gone. – Jarsen Apr 27 '12 at 05:03

4 Answers4

3

It seems like your problem is in the way you're defining your properties.

You're using assign rather than strong, or copy.

In a nutshell, it's because strong implies that you want your object to be retained.

Using copy implies that you want to create a new copy of an object or a value and set that as value of your property... As Mario and Jarsen explain, using copy is better practice when working with arrays to prevent the array being mutated (i.e. values changed) while it is being enumerated / traversed. Using copy also retains the new object.

If you're using ARC and your objects are not retained, then they will be released automatically by the compiler.

Using assign means that you assume the new object has been retained elsewhere and that you don't want to retain it again.

I suppose what was happening is that you were assigning your variable to your property, but the variable was being released (and hence resulting in nil) and causing the crash.

Here are a few links:

New to Objective C: Need help understanding strong reference vs assign

Objective-C ARC: strong vs retain and weak vs assign

Clarification on assign, retain, copy, strong?

Community
  • 1
  • 1
C4 - Travis
  • 4,502
  • 4
  • 31
  • 56
  • copy would likely be an even better choice, as Mario suggests. Using copy instead of strong on properties such as NSString or NSArray which have mutable subclasses is a good practice because it protects you from accidentally mutating that value since that you typically want to hold onto the value received at assign-time. – Jarsen Apr 27 '12 at 05:19
  • @C4-Travis Effectively Now I am using copy and assigning my properties with self.playerName = n and self.playerScore = 0. Everything is working! Thanks for the links. – ivantxo Apr 27 '12 at 21:51
2

Your playerName property should best be copied instead of assigned

@property (nonatomic, copy) NSString *playerName;

When trying to access the assigned value, the object most likely is gone causing the bad access.

Also remember to release playerName in dealloc when you set the property to copy.

Cheers

Mario
  • 4,530
  • 1
  • 21
  • 32
  • That's a start, but it still won't be retained by the init: given above :) – davehayden Apr 27 '12 at 05:07
  • Absolutely, self.playerName = n is what he needs – Mario Apr 27 '12 at 05:10
  • @Mario thank you Mario I am using copy now and everything works smoothly. I am also assigning my properties with self.playerName=n and self.playerScore=0. Thank you very much. – ivantxo Apr 27 '12 at 21:53
1

You just want to enumerate the array?

for (CustomClass *object in myArray){
  [object printPlayer];
}
Mike Z
  • 4,121
  • 2
  • 31
  • 53
  • It happens the same. At some point when I add more players, usually 3 or 4 the printPlayer code crashes. – ivantxo Apr 27 '12 at 01:15
1

Either what Mike Z said or the "crude":

for (int i = 0; i < myArray.count; i++) {
    CustomClass* object = [myArray objectAtIndex:i];
    [object printPlayer];
}

While there are more elegant schemes, you can clearly understand what this one is doing, and how an NS(Mutable)Array is just a simple analog to a standard C array.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151