why can't we store C struct directly in NSArray
c, objective-c
Solution
It should be noted that the reason we can't put C-structs into `NSArray` isn't because of anything special about structs. Instead, we should consider `NSArray` to be a special type of array.
We can put structs in arrays in Objective-C. We know this because C programmers put structs in arrays.
`NSArray` (and `NSMutableArray` and all the other `NS` collection objects) is a special class designed to implement the array data structure specifically for Objective-C objects. The fact that `NSArray` only allows Objective-C objects allows `NSArray` to do things like `makeObjectsPerformSelector:`. We're sending an Objective-C message to everything in the array. We couldn't allow this if we allowed non-Objective-C-objects into the array.
It's not just `structs` that aren't allowed into `NSArray`. All the primitive data types are not allowed in an `NSArray`. This even includes `NSInteger` and `CGFloat`, because remember, these are typedef'd primitives--not objects.
It should be noted however, that `NSArray` is not the only array-like data structure available to us in Objective-C. Remember, Objective-C is a strict superset of C. And as I already mentioned, C programmers are already putting structs into an array.
We can always use a C-style array. In fact, although it's very rarely done (because of the power of Objective-C arrays), we can even create a C-style array of Objective-C objects.
Consider:
NSString *stringArray[3];
stringArray[0] = @"foo";
stringArray[1] = @"bar";
stringArray[2] = @"baz";
for (int i = 0; i < 3; ++i) {
NSLog(@"%@", stringArray[i]);
}
This compiles, runs, and does exactly what you'd expect in Objective-C. As such, we can do exact same with a `struct`:
typedef struct Foo {
int x;
int y;
} Foo;
Foo fooArray[3];
fooArray[0] = (Foo){.x = 1, .y = 2};
fooArray[1] = (Foo){.x = 3, .y = 4};
fooArray[2] = (Foo){.x = 5, .y = 6};
for (int i = 0; i < 3; ++i) {
NSLog(@"Foo(x: %i, y: %i)", fooArray[i].x, fooArray[i].y);
}
Again, this is perfectly valid Objective-C code.
The question you have to ask yourself: Is it better to have a struct and deal with a C-style array, or would my struct be better as an object that I can put in an `NSArray`? I wouldn't use a `struct` that I'm converting to `NSData` and back just for the sake of putting it into an `NSArray`...that seems like a mess.
Problem
I ran into an error when I was trying to store a C struct into a NSArray (I was able to solve it by converting into NSData as specified in the link below). However, I am curious to understand why it did not work without all this hassle of using NSData. link to solution I used Please note: I don't want a solution, it is already solved. I am just trying to improve my understanding of the fundamentals of Objective-C by understanding why the direct approach below did not work. What I was trying to do: A simple program that allows a person to add a grocery item and mark it as done after adding to shopping cart Define C struct with 3 elements (name of item, count and BOOL to keep track of whether it has been added to cart or not) Each time a new item is created I do the following groceryItem *secondGroceryItem = malloc(sizeof(groceryItem)) ; secondGroceryItem->itemName="Beer" ; secondGroceryItem->count = 3 ; secondGroceryItem->purchased=NO ; Then I add it to a NSMutableArray keeping track of grocery items using [myGroceryList addObject:(__bridge id)(secondGroceryItem)] where myGroceryList is defined earlier as NSMutableArray *myGroceryList = [NSMutableArray array] ; This does not work. I had to convert into a NSData before storing in NSMutableArray. Why can't I just store a pointer to my C struct directly in the NSMutableArray?