0

I'm trying to save all the variables in my class into NSUserDefaults using objc/runtime. And below is the code I'm using.

NSUInteger count;
Ivar *iVars = class_copyIvarList([self class], &count);
for (NSUInteger i=0; i<count; i++) 
{
    Ivar var    = iVars[i];
    NSString *varName = [NSString stringWithCString:ivar_getName(var) encoding:NSUTF8StringEncoding];
    NSString *varType = [NSString stringWithCString:ivar_getTypeEncoding(var) encoding:NSUTF8StringEncoding];

    if([varType hasPrefix:@"["])
    {
        NSLog(@"Array");
        id var1 = [_manager valueForKey:varName];

        NSLog(@"--- %@", var1);

        NSData *data = [NSData dataWithBytes:&([_manager valueForKey:varName]) length:sizeof([_manager valueForKey:varName])]
        [[NSUserDefaults standardUserDefaults] setObject:[_manager valueForKey:varName] forKey:varName];
    }
    else
    {
        NSLog(@"NonArray");
        NSLog(@"---  %@", [_manager valueForKey:varName]);
        [[NSUserDefaults standardUserDefaults] setObject:[_manager valueForKey:varName] forKey:varName];
    }

}

free(iVars);

The problem is that, when there are only primitive datatypes, the above code works just fine. But, when I try to access a array variable like int[], or float[], it gets crashed with SIGABRT. it is not showing any other messages.

valueForKey doesn't return any values for C arrays.

If anybody know how to load values for C-arrays in runtime, please help.

Thanks in advance,

Suran

2
  • 1
    Try using objectForKey instead of valueForKey. Commented Dec 16, 2011 at 9:01
  • But, my class is a subclass of NSObject, not any class like NSMutableDictionary etc, and when I try to use objectForKey it is just showing a warning that, it can't find the method Commented Dec 16, 2011 at 9:33

1 Answer 1

2

Unless you always provide a paired length method, your program will never know the length of the array returned. So... you will need to do some work someplace to accomplish this without a crash.

If I really wanted to do what you're doing, I would make the class itself create the array, providing NSData. If this is common, you may want to use a convention:

 - (int*)pixelBuffer;
 - (NSData *)pixelBufferForSerialization; // << returns a deep copy of
                                          //    self.pixelBuffer as an
                                          //    NSData instance.

So your above implementation would see that the property defines a scalar array, and then request NSData * data = obj.pixelBufferForSerialization; instead of trying to produce the data itself.

Update

It's best to let the class do it. Here's how to create NSData using such an array:

@interface DataManager : NSObject
{
@private
    int* things;
    size_t nThings;
}

- (int*)things;
- (NSData *)thingsAsNSData;

@end

@implementation DataManager

- (int*)things
{
    return things;
}

- (NSData *)thingsAsNSData
{
    // note: you may need to choose an endianness for serialization
    if (0 == nThings) return [NSData data];w
    return [NSData dataWithBytes:things length:nThings * sizeof(things[0])];
}

@end

Again - you want the class to create the data because it knows its own structure best.

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

5 Comments

Hi Justin, thanks for the answer but, I didn't get you. Can you explain, how can I achieve this?
@Suran C arrays don't define length, so you need to save the length someplace. So you need to also keep track of the length of the buffer - it's easiest for the class itself to manage the buffer and the buffer's length. So the easy way would be to move the creation of the NSData to the class because it should know the length. Then you can create a convention (I suggested a suffix *property*ForSerialization) for returning deep copies of the buffers as NSData (outlined above). Then you can compose a string from selector+suffix, and then convert that string to a selector to get the data.
Can you post some code regarding this? I'm not able to grasp it. Also, to get the size of the array, can't we just use sizeof operator?
@Suran a) I don't know specifically what code you want (to avoid writing everything, which takes time) b) the sizeof operator will not work - it will return the size of a pointer regardless of the number of elements in the array.
The thing is that, what I'm trying to accomplish is to get the value of an C array that is a property of the class 'DataManager' of which, '_manager' is an instance. I've saved the property name and property type into two variables varName and varType respectively. Now, I need to retrieve the state of that C array. I'd be really thankful if you can provide me with some sample code to get the value of the C array.

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.