Get all the variable names or attributes of a #interface - iphone

I want all the variables names or attributes of a interface or class in objective c.
I am able to get and set the value for a variable dynamically using valueForKey: message.

If you are looking to get all 'properties' for a class, you can utilize the Objective-C runtime to get this data:
unsigned int propertyCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
for(i = 0; i < propertyCount; i++)
{
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
}
free(properties);
With this object you can get all of the metadata associated with a given property. This isn't for the faint of heart though (and it is a C based API). Determining information about each property (like it's policy and type) isn't simple.

Take a look at the Objective-C Runtime Reference and in particular the class_copyIvarList and class_copyPropertyList functions. Use of these runtime functions should be what you're looking for.

Related

How to dynamically change a property that is being accessed

I'm programming a game that has 40 levels and I'm storing all my level data in a .plist. This works great but now that I'm trying to implement multiple levels, I'm looking for a way to call a property on a singleton based on level without manually coding something like a switch/case. I would like to do something like the following:
This is the code I use to pull my data but as you can see, I've hard coded the "dictionaryLevel1Data" property.
int capacity = [[sharedDataManager.dictionaryLevel1Data objectForKey:#"typeWarrior"] intValue];
I would like to set a variable and have the property of the singleton called based on that like this which I know doesn't work. Notice how I'm replacing "dictionaryLevel1Data"
NSString level = #"1";
int capacity = [[sharedDataManager.[NSString stringWithFormat:#"dictionaryLevel%#Data", level] objectForKey:#"typeWarrior"] intValue];
Any suggestions on how I could accomplish this would be greatly appreciated. I can always go and manually setup a switch/case for each level but with 40 levels and 50+ different object types per level it would be rough, it seems like there must be a better way. I hate hard coding values and like to simplify my code with easy updates to variables that run through generic classes and methods.
why don't you do like this;
use 2 level data map;
//sharedDataManager.levelData is a NSDictionary that contains lots of NSDictionarys
NSDictionary *levelData = [sharedDataManager.levelData objectForKey:[NSString stringWithFormat:#"dictionaryLevel%#Data", level]];
int capacity = [levelData objectForKey:#"typeWarrior"] intValue];
If you want do it this way, then you can use Key-Value-Coding, to get a property value from a string. The accepted answer in this post shows how to use it (very easy): Objective-C get a class property from string
For your task it would look something like this:
int capacity = [[[sharedDataManager valueForKey:[NSString stringWithFormat:#"dictionaryLevel%#Data", level]] objectForKey:#"typeWarrior"] intValue];
You can use :
NSString level = #"dictionaryLevel1Data"
SEL methodSelector = NSSelectorFromString(level);
if ([sharedDataManager conformsToSelector:#selector(methodSelector)]) {
NSDictionary *levelData = [sharedDataManager performSelector:methodSelector];
// Do whatever you need here
}
I assume all dictionaryLevelData are synthesized and have getters as their name.
(Note that I did not compile it but it should work)

Is it possible to access all properties of an object using id?

I have an Object: aObject, it has properties a,b,c.
I can access the properties using:
aObject.a
aObject.b
aObject.c
Is it possible to access all properties of the object using id? such as
[aObject indexOf:0]
[aObject indexOf:1]
[aObject indexOf:2]
or something likes that.
Welcome any comment
Even if I never used it, it seems it's possible with class_copyPropertyList method.
KVC (Key Value Coding) will allow you to set values of properties using the method [anObject setValue:aValue forKey:#"a"].
If you truly want to iterate through each property, setting its value, then you will need to drop down to the objective-c runtime.
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([anObject class], &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char * name = property_getName(property);
[anObject setValue:anyValue forKey:[NSString stringWithUTF8String:name]];
}
free(properties);

OBJECTIVE-C Stack with array of int

I would like to create a stack with array of int (2 dimensional : int[9][9]), but I can't.
I tried the NSMutableArray which needs objects. So I tried to use NSValue to transform my array to a NSObject, but I keep having lot ouf trouble.
Can you please give me some help ?
I push an array (a grid) in the (void)saveGrid function.
I need to recover the last grid in the (IBAction)undo function.
Here is my last-try code source : (where Im transforming my 2D-array (9*9) to a 1D-array (81))
- (void)saveGrid {
int longGrid[81];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
longGrid[(i+1)*(j+1)-1] = matrix[i][j];
}
}
NSValue *valObj;
valObj = [NSValue value:&longGrid withObjCType:#encode(int **)];
[TGrid addObject:valObj];
}
- (IBAction)undo:(id)sender {
[TGrid removeLastObject];
int *valPtr;
[[TGrid lastObject] getValue:&valPtr];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
matrix[i][j] = valPtr[(i+1)*(j+1)-1];
}
}
}
(TGrid is NSMutableArray typed.)
Thanks for your help !
I don't really understand your thinking. You want to use an NSArray, correct? Or NSMutableArray? Either way, you can't store ints in these. You can only store objects, so an integer would be an NSNumber object. It's actually a subclass of NSValue, so you don't need to use NSValue.
So with that it's pretty easy to create an NSMutableArray, populate it with the numbers, which are of the NSNumber object, and then create another NSMutableArray and populate that one with a bunch of NSMutableArrays. There you have it, a 2 dimensional array.
Secondly, It's not a good idea to subclass NSArray, NSDictionary, NSString, and the mutable versions of that. In Cocoa, many classes are actually implemented as class clusters, which are a bunch of implementation-specific classes hidden behind a common interface. When you make an NSString object, you might actually end up getting an NSLiteralString, NSCFString, NSSimpleCString, NSBallOfString, or any number of undocumented implementation-detail objects.
You should use NSNumber. Checked that out? Otherwise you could go for an C Array.
If your problem is to put a 2D array of int into an object, why not do just that? Create a class containing one property of type int[9][9], create an object of that class and put your array in it.
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayerArray addObject:]: unrecognized selector sent to instance 0x4b36ce0'
I think that TGrid is getting autoreleased. Try this:
TGrid = [[NSMutableArray alloc] initWithCapacity:10];
Then release it in your -dealloc method of course.

iPhone OS: Get a list of methods and variables from anonymous object

I am building my first iPhone/Obj-c app and I have a large amount of data-holding subclasses that I am passing into a cite function. To the cite function these objects are anonymous and I need to find a way to access all the variables of each passed object.
I have been using a pre-built NSArray and Selectors to do this but with more than 30 entries (and growing) it is kind of silly to do manually. There has to be a way to dynamically look up all the variables of an anonymous object.
The obj-c runtime run-time docs mention this problem but from what I can tell this is not available in iPhone OS. If it is then I don't understand the implementation and need some guidance. A similar question was asked before but again I think they were talking about OSX and not iPhone.
Any thoughts?
-(NSString*)cite:(id)source {
NSString *sourceClass = NSStringFromClass([source class]);
// Runs through all the variables in the manually built methodList
for(id method in methodList) {
SEL x = NSSelectorFromString(method);
// further implementation
// Should be something like
NSArray *methodList = [[NSArray alloc] initWithObjects:[source getVariableList]]
for(id method in methodList) {
SEL x = NSSelectorFromString(method);
// Further implementation
}
The runtime is the same on the Mac as it is on the iPhone. If the other question does what you're looking for, then it should work. If it doesn't, file a bug.
In the meantime, given a Class, you can retrieve a list of all of its selectors using the class_copyMethodList() function:
unsigned int numMethods = 0;
Method * methods = class_copyMethodList(sourceClass, &numMethods);
NSMutableArray * selectors = [NSMutableArray array];
for (int i = 0; i < numMethods; ++i) {
SEL selector = method_getName(methods[i]);
[selectors addObject:NSStringFromSelector(selector)];
}
free(methods);
It's certainly possible to do this through the Objective-C runtime functions, but it's probably not the right way to go about it. Since you're creating the objects passed into the cite method, just have them each implement a protocol that cite can use to extract whatever information it needs.
Something like the Key-Value Coding protocol will probably do what you want:
http://developer.apple.com/iphone/library/documentation/cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html

Return all properties of an object in Objective-C

Is it possible to return a list of all the properties implemented by an object in Objective-C?
I understand the properties are just getters and setters so I'm not sure how it would work. If this cannot be done, then is it possible to return all the selectors that an object will respond to? I'm looking for something similiar to the "methods" method in Ruby.
// Get properties list
objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount);
// Get methods list
Method* class_copyMethodList(Class cls, unsigned int *outCount);
The following code will output all methods implemented in UIImage class to console:
unsigned int count;
Method* methods = class_copyMethodList([UIImage class], &count);
for (size_t i = 0; i < count; ++i)
NSLog([NSString stringWithCString:sel_getName(method_getName(methods[i]))]);
free(methods);
I was actually trying out this yesterday and it is possible, however you cannot get everything from UIView.
Take a look at the Objective-C Runtime Reference