-2

I am trying create an NSArray which holds the datatype of serialized files i will be loading from disk.
It can say double, int, or some custom type, and then I will need to load those files and cast them to double/int/custom type.

Is there a way I can store types in NSArray but not store strings?
so far, it seems that there is no way but to use stringified types as I show in this example.

any ideas?

S1LENT WARRIOR
  • 11,704
  • 4
  • 46
  • 60
sramij
  • 4,775
  • 5
  • 33
  • 55
  • 3
    Take a look at [`NSValue`](https://developer.apple.com/documentation/foundation/nsvalue?language=objc) — you can use it to wrap any type into an ObjC object. – Itai Ferber Jan 31 '18 at 16:57
  • 1
    OK, now that I understand the problem, I was going to suggest stringification, and guess what, you've already thought of that. Just make up your own encoding (as it were) for recording the desired information, and do it. In the time you've spent playing around with this question on Stack Overflow, you could have had this implemented by now. — Note also that you cannot ask a C primitive "what type are you?" The notion makes no sense. – matt Jan 31 '18 at 17:25
  • 4
    Now that you've clarified your question a bit: no, you can't store types directly in an `NSArray`, since types have no runtime representation. `int` doesn't exist past compilation, only what `int` can do. Your alternative is to use strings, as @matt suggests, but I wouldn't recommend making up your own encoding. Objective-C has the `@encode` compiler directive which gets you a stable string for a given type. For instance, `@encode(int)` returns `"i"`, `@encode(double)` is `"d"`, and `@encode(const char *)` is `"r*"`. – Itai Ferber Jan 31 '18 at 17:32
  • See at [type encodings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html) for more info. – Itai Ferber Jan 31 '18 at 17:32
  • 1
    I don't know why the down voting, **** it. Thanks Itai, I ended up using @encode, I learned about it from your earlier hint about NSValue. – sramij Jan 31 '18 at 17:49

2 Answers2

2

Wrap the primitive value in an NSNumber or NSValue. Use NSNumber for simple numeric values (Boolean, integer, floating point, decimal, ...). Use NSValue for more abstract structures (NSRect, for example) and any encodable C type. Here's an example:

NSUInteger a = 1234;
double b = 12.34;
NSRect c = NSMakeRect(0.0,100.0,200.0,300.0);
SomeWeirdCType d = ?
NSMutableArray<NSValue*>* valueList = [NSMutableArray array];
[valueList addObject:[NSNumber numberWithUnsignedInteger:a]]; // legacy
[valueList addObject:@(b); // modern ObjC compiler syntax, auto-boxes as NSNumber
[valueList addObject:[NSValue valueWithRect:c]];
[valueList addObject:[NSValue value:&d withObjCType:@encode(SomeWeirdCType)]];
James Bucanek
  • 3,299
  • 3
  • 14
  • 30
  • I don't have values to store such as 'b' and 'd'. I just wanna store the type. – sramij Jan 31 '18 at 17:07
  • Arrays do not hold types. They store values. – James Bucanek Jan 31 '18 at 17:09
  • Well, that's my question is about. hopefully someone has a creative idea here. – sramij Jan 31 '18 at 17:10
  • 1
    @sramij What creative idea? You are the who hasn't asked your question clearly. It is totally unclear what you could possibly be trying to do. – matt Jan 31 '18 at 17:12
  • 1
    NSArray stores object references. `Arr[I]` will always be an object. Period. No exceptions. So it will never be a pointer to an `int`. If you're really interested in knowing if `Arr[I]` is of type `int*`, I can answer that question for you: _never_. ;) Please explain in more detail what you're trying to do. – James Bucanek Jan 31 '18 at 17:16
  • @matt sorry about the unclarity, i have re-written my question, hopefully it makes sense now .It doesn't mean there should be an answer though. – sramij Jan 31 '18 at 17:22
2

C types are not something you can store. There's no C code like:

type types[10];
types[0] = typeof(int);

*target = *(types[0] *)&source;

Objective-C has type awareness, but would require you to map all of your original data to an Objective-C class. E.g.

NSArray *objects = [[NSArray alloc] init]; // Old-school non-lightweight-templated, to hold anything

[objects addObject:[NSNumber numberWithInt:23]];
[objects addObject:[NSNumber numberWithFloat:23.0f]];
[objects addObject:@"I'm a string"];

...

if([objects[0] isKindOfClass:[NSString class]]) {
    NSLog(@"Object zero is the string %@", objects[0]);
}
if([objects[0] isKindOfClass:[NSNumber class]]) {
    CFNumberType numberType = CFNumberGetType(number);
    ... table here to map the enum numberType to a string ...
    NSLog(@"Object zero is a number of type %@ with value %@", type, objects[0]);
}

You can't in general store types without values; this is because there's really no value whatsoever in doing so. Type and value are inherently connected — severing them while keeping type explicit and retaining a one-to-one mapping suggests a severe design deficiency.

Tommy
  • 99,986
  • 12
  • 185
  • 204