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?
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.
An NSArray or NSMutableArray consists of objects. C datatypes are not objects. So you can not store them directly in a NSArray.
I assume that you know how to create an object. Include in this object the variables with the C-datatype.
Once you have that, add that object to the NSArray:
NSMutableArray *yourArray = [[NSMutableArray alloc] init];
YourObject *object1 = [[YourObject alloc] init];
[yourArray addObject: object1];
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.