2

I'm trying to store some data in an NSMutableArray. This is my struct:

typedef struct{
    int time;
    char name[15];
}person;

This is the code to add a person:

person h1;
h1.time = 108000;
strcpy(h1.name, "Anonymous");
[highscore insertObject:[NSValue value:&h1 withObjCType:@encode(person)] atIndex:0];

So, I try to extract in this way:

NSValue * value = [highscore objectAtIndex:0];
person p;
[value getValue:&p];
NSLog(@"%d", p.time);

The problem is that the final log doesn't show me 108000!
What is wrong?

3
  • Is there any particular reason you're using a c struct rather than an actual object? Unless you do, go with objects. Commented Jul 6, 2012 at 16:07
  • I don't know another way to store two type of data(int and string) in the same index. I have corrected "persona", sorry. Commented Jul 6, 2012 at 16:12
  • @user1431646 Create a custom class. Commented Jul 6, 2012 at 16:14

3 Answers 3

2

Your code looks correct (and works for me), so I deduce that you aren't initializing highscore. So when you send the insertObject:atIndex: message to it, nothing happens. When you then send the objectAtIndex: method to it, you get nil back. When you send getValue: to the nil NSValue *value, it does nothing, so your person p is left filled with random stack garbage, which is why your NSLog doesn't print 108000.

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

Comments

1

As stated in my initial comment there rarely is a reason to do this kind of stuff with pure c structs. Instead go with real class objects:

If you're unfamiliar with the syntax below you may want to look at these quick tutorials on ObjC 2.0 as well as read Apple's documentation:

Person Class:

// "Person.h":
@interface Person : NSObject {}

@property (readwrite, strong, nonatomic) NSString *name;
@property (readwrite, assign, nonatomic) NSUInteger time; 

@end

// "Person.m":
@implementation Person

@synthesize name = _name; // creates -(NSString *)name and -(void)setName:(NSString *)name
@synthesize time = _time; // creates -(NSUInteger)time and -(void)setTime:(NSUInteger)time

@end

Class use:

#import "Person.h"

//Store in highscore:

Person *person = [[Person alloc] init];
person.time = 108000; // equivalent to: [person setTime:108000];
person.name = @"Anonymous"; // equivalent to: [person setName:@"Anonymous"];
[highscore insertObject:person atIndex:0];

//Retreive from highscore:

Person *person = [highscore objectAtIndex:0]; // or in modern ObjC: highscore[0];
NSLog(@"%@: %lu", person.name, person.time);
// Result: "Anonymous: 108000"

To simplify debugging you may also want Person to implement the description method:

- (NSString *)description {
    return [NSString stringWithFormat:@"<%@ %p name:\"%@\" time:%lu>", [self class], self, self.name, self.time];
}

which will allow you to just do this for logging:

NSLog(@"%@", person);
// Result: "<Person 0x123456789 name:"Anonymous" time:108000>

2 Comments

Thank you all, I correct all things, but the real mistake I've made was I forgot to initialize the array!
@user1431646: still, go with objects. There is no reason not to. Yet hundreds in favor of it. Way easier name string handling and memory allocation just to begin with.
0

Reimplement Person as an Objective-C object and reap the benefits:

Person.h:

@interface Person : NSObject
{
    int _time;
    NSString *_name;
}

@property (assign, nonatomic) int time;
@property (retain, nonatomic) NSString *name;

@end

Person.m:

#import "Person.h"

@interface Person
@synthesize time = _time;
@synthesize name = _name;

- (id)init
{
    self = [super init];
    if (self != nil)
    {
        // Add init here
    }
    return self;
}

- (void)dealloc
{
    self.name = nil;
    [super dealloc];
}

@end

2 Comments

There is no need to declare the private members in the interface, @property and @synthesize is enough. Also, with ARC the dealloc (and the init) are both unnecessary. With 4.5 even @synthesize can be removed, leaving only the property declarations.
@HampusNilsson This is the style I prefer to use and this implementation should work across pretty much any compiler and memory environment.

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.