Writing struct into NSMutableArray - objective-c

I have a game object which processed in two completely different places. In Contact Listener i check some conditions and if they occur i must save one or more portions of complex data. So i decided to use struct. For example:
struct SomeStruct
{
int value1;
int value2;
CGPoint value3;
b2Vec2 value4;
};
typedef SomeStruct SomeStruct;
In Game Scene i go through all game objects and if its the stack/array not empty, do some stuff and wipe it.
In Contact Listener it repeats from the beginning.
I must use this architecture because of strict order of execution (method must be called after other methods).
I suspect that i need something like vector or NSMutableArray (i think it will not work with struct), so vector may the the only way.
But don't understand how to achieve it. May you help me with some code/pseudocode or link to the book/article where i can found a solution?

Cocoa provides NSValue class for that purpose:
This creates an object that you can add to NSMutableArray:
NSValue *someObj = [NSValue valueWithBytes:&myStruct objCType:#encode(SomeStruct)];
You can use [someObj pointerValue] to access a void* representing the address of the structure that you put in NSValue.

There is a lot of solutions for this problem.
Don't use struct. An obj-c class is practically the same thing as a struct.
Use CFArray (CFArrayCreateMutable) and put it there as a pointer.
Use a C++ class with STL vector.
Use a C array (SomeStruct[]) and increase its length when you need it.
Use a classic implementation of a stack, with a linked list (every struct has a pointer to the next value).

Related

Automatically running a selector on instance creation

In Objective-C, is there any way to run a specific selector automatically every time an object is instantiated? (I know about +initialize but I need an instance method).
Specifically, I am writing a custom string class (that inherits from my own root class with a similar interface to NSObject) and I am trying to make it 'play nicely' with Objective-C constant strings. To do this, I have the following class definition (as required by the runtime):
// 1) Required Layout
#interface MYConstantString : MYObject {
//Class isa; inherited from MYObject
char *c_string;
unsigned int length;
}
Now, I want to implement my string class by using a pointer to a C-struct inside the class (this "C object" is already well implemented so I basically just want to wrap it in an Objective-C class). Ideally therefore, my Objective-C class would look like this:
// 2) Desired Laout
#interface MYConstantString : MYObject {
// Class isa;
StringObject *string;
}
And then the class and instance methods would just wrap C function calls using that StringObject.
So because I can't have the desired ivar layout (2), I wish to hack around the required ivar layout (1) to work for me. For example:
- (void)fixup {
// Pseudocode
temp = copystring(c_string);
c_string = (void *)StringObjectNewWithString(temp); // Fudge pointer
length = ... // I can do something else with this.
}
So, to return to the question, is there a way to call -fixup automatically, rather than having to do the following every time I make write an Objective-C constant string?
MYConstantString *str = #"Constant string";
[str fixup];
I know this is an obscene hack, and Objective-C constant string interoperability isn't totally crucial for what I need, but it would be nice to be able to use the #"" syntax and make the code more 'naturally' Objective-C.
I'm guessing you left out an important fact: you're using -fconstant-string-class=MYConstantString when building to have the compiler use your class for constant string objects (#"...").
Given that, then, no. There are two significant problems. First, "instance creation" for constant strings happens at compile time, not run time. The reason that there's a required layout is that the compiler does nothing but lay out the string's data in a data section with a reference to the appropriate class object where the isa pointer goes. It doesn't invoke any custom code. It is not necessarily even aware of such custom code at compile time. A given translation unit may not include the constant string class. The reference to that is resolved at link time.
Second, the constant string instance is almost certainly laid out in a read-only data section. There's a good chance that even calling your -fixup method manually as in your question would encounter an access violation because you'd be modifying read-only memory.
You should consider using a class cluster. Make MYConstantString one concrete subclass of an abstract base class. Make it conform to the required layout and just use the character pointer and length ivars as they are. If it would be convenient to translate to StringObject at various points, do that at those points. Implement other, separate concrete subclasses to use StringObject internally, if desired.
MYConstantString *str = #"Constant string";
That can't work because #"..." is an NSString, and it's not only a problem of layout but of instance sizes. If you want 0-copy or anything like that, what you have to do is have something like:
MYConstantString *str = [MyConstantString stringWithNSString:#"Constant string"];
and let -stringWithNSString: recognize when the passed string is a constant one (I'm pretty sure the concrete class of constant strings is easy to recognize, and probably hasn't changed ever for backward compatibility reasons) and then hack it around to grab the pointer to the bytes and similar things.

Box Custom Struct in Objective-C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to wrap a Struct into NSObject
Can the new Clang Objective-C literals be redirected to custom classes?
I have a custom struct:
typedef struct {
float f1;
float f2;
} MYCustomStruct;
that I need to add to an NSArray. I've already written a category to create NSValues of these structs, which I then add to the NSArray, however I'd like to simplify that even further using boxed expressions, if possible. I'd love to be able to do this:
#[#(instanceOfMYCustomStruct)];
however, I'm confronted with the following error:
Illegal type 'MYCustomStruct' used in a boxed expression
Is there a way to use boxed expressions with custom structs?
I would use a NSValue to box a struct, as it has built-in support for it. Unfortunately, you cannot use objective-c's cool literals for it, though:
struct foo myStruct;
NSValue *val = [NSValue valueWithBytes:&myStruct objCType:#encode(typeof(myStruct))];
// to pull it out...
struct foo myStruct;
[val getValue:&myStruct];
While this may be unwieldy & ugly amidst other objc code, you have to ask yourself - why are you using a struct in the first place in Objective-C? There are few speed performances gained over using an object with a few #property(s), the only real reason I could see is if you are integrating with a C library for compatibility with memory layouts, and even then, the structure of an objective-c object's memory layout is well-defined, so long as the superclass doesn't change.
So what is your real purpose in boxing a struct? If we have that, we can help you further.

Are pointers to arguments in Objective C methods are const by default?

There are methods in Cocoa classes that accept an address of a pointer. Most commonly the argument is address of future NSError * object in CoreData validation methods (among others). This way it is possible to put custom or owned object into the place of the address that given argument points to.
My question is: why can't we do that with simple pointer arguments? E.g. let's say I have a method:
- (void)addObject:(id)someObject toArray:(NSMutableArray *)array;
I can easily pass the mutable array as second argument, call addObject: on it and after the method call the array will be modified. Why is this not done with NSError * objects? Are pointers passed to methods are defined as const by default? Is this to avoid accessing NULL?
Why is this not done with NSError * objects?
Because there's no such thing as an NSMutableError. Your example works because you can modify the contents of the array without modifying the pointer to the array itself. However, since NSError instances are immutable, you cannot modify an NSError. As such, you must necessarily create a new error object. And if you want to return that error object along with some other piece of data, at least one of those must be done via an out-parameter (such as an NSError **).
Are pointers passed to methods are defined as const by default?
Nope. Inside that method you're welcome to do this:
- (void)addObject:(id)someObject toArray:(NSMutableArray *)array {
someObject = somethingElse;
[array addObject:someObject];
}
What's important to remember here is that you're only changing a pointer in a slot in memory. The memory slot corresponding to someObject is just a space on the stack, and you're changing the contents of that space to have a value that points to a different allocated object than the one you were given.
Is this to avoid accessing NULL?
Any NULL protection you need must be done yourself.
It's because the NSError class does not define any way to modify instances after creation. The pointer itself is mutable, but an NSError is not.
They are all plain C pointers. They are not const unless you make them const. Const pointers are not a good thing to use in most situations in objective-C, or even often plain C. Const pointers are a subtle concept, and the complexities of the meaning and syntax don't mesh well with the Objective-C style of programming. Forgetting they exist is likely a good first approximation.
Example: NSArray and NSMutableArray - we would not need an NSArray class if const worked 'correctly' - but it can't due to the design of C.
** - For NSError, etc., the idea is to create an NSError, not alter the one you have passed in. In other words, you need a pointer to a pointer to be able to create an instance (i.e. change the actual object).

Looking for suitable Objective-C object to wrap C void * pointer

I'm working on a project that has C code embedded within Objective-C code. The C code produces some void * pointers that I would like to pass between Objective-C methods, so I'd like to wrap them in Objective-C objects to make an NSSet or something to that effect.
I have looked into NSData, which seems to accept arbitrary data, but wants to know the length of the memory chunk, that I don't have.
Any help is appreciated.
The NSValue class is usually used for this task:
NSValue* value = [NSValue valueWithPointer: myPointer];
and
void* myPointer = [value pointerValue];
Note, though, that the pointer given will not receive any special treatment with respect to memory management. You (and you alone) are responsible for making sure, that the memory it points to remains valid as long as pointers to that memory region exist and are reachable in some part of your program.
Note, though, that using such a value with NSSet or as key in a NSDictionary might or might not yield the intended effect:
NSData is essentially a byte buffer. It actually represents the content of the memory in question. Comparing NSData instances for equality compares at byte level. This is one of the reasons, NSData needs to know about the length of the memory region in question.
NSValue with a pointer value is an entirely different beast. Here, that actual (numeric) pointer value is the essential thing. No consideration is given (when comparing two NSValue instances) to the actual content at the address.

Better alternative for "data-only" Objective-C objects?

I run into design choices like this often and struggle a bit; I'm looking for some other perspectives.
I often want to keep lists of, or pass around chunks of state that are basically just sets of values. The values tend to be primitive types: floats, NSTimeIntervals, CGPoints, etc.
My first inclination is often to create C structures for these sets of properties, e.g.
typedef struct _STATE {
float foo;
NSTimeInterval elapsed;
CGPoint point;
} STATE;
etc.
But C structures don't play nicely with the native Cocoa collection classes (NSArray, NSSet, NSDictionary), and using overmany of them to track lots of state feels like it runs against the grain of rest of my Cocoa-friendly code-- I end up having and directly managing arrays of structs, and passing struct pointers around in messages, etc.
On the other hand, since raw performance isn't necessarily critical, I could encode these values into a NSDictionary, wrapping them all in NSValue or NSNumber, but the resulting syntax is hardly terse, and a little fragile, requiring type and name correctness at runtime for both the insert and the lookup:
[stateDict setObject:[NSNumber numberWithFloat:foo] forKey:#"bar"];
...
float something = [[stateDict objectForKey:#"bar"] floatValue];
and some types, like NSTimeInterval, are only able to be used with some (arguable) hackery (typecast to double in that case).
Finally, I could create data-only container objects, with private member data and only getters/setters. (These would be called "beans" in Java.) These are more terse to access than dictionaries, more Cocoa than structs, but feel like overkill to me, especially if I only need them as "inner classes" that are used for state management internal to a single object type.
How do you, great Cocoa programming public, do this?
Depending on the situation, I run either with using NSDictionary classes for arbitrary data, or I create container classes (the #property/synthesize tags in Objective C make this really easy). By using ObjC for the header file:
#interface StateObject : NSObject {
NSNumber *foo;
NSTimeInterval *elapsed;
CGPoint point;
}
#property (retain) NSNumber *foo;
#property (retain) NSTimeInterval *elapsed;
#property (copy) CGPoint point;
#end
One can then use #synthesize <variable> in the .m file to automatically create the setters/getters. Then, while anonymous NSNumbers are still ornery, you can do:
myStateObject.foo = [NSNumber numberWithFloat:7.0];
This should take most of the pain away, and let you use the Cocoa collection classes to better shuffle data around.
Not necessarily endorsing this approach as "best", but there is a middle ground between your proposals: create C structs to hold the information, and then wrap the structs in NSValue objects when you need to put them into Cocoa data structures. You can see UIKit do this in some cases with structs like CGPoint in notifications (and I'm sure that AppKit does, as well).
See "Using Values" in Number and Value Programming Topics for Cocoa for more on that.