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);
Related
I am getting a list of all ivar using the following:
Ivar *vars = class_copyIvarList([property class], &varCount);
My question is how do I create an id from an Ivar? I.e. recover an NSString or NSDictionary, etc.
You just use object_getIvar() function.
Something like this:
uint varCount;
Ivar *vars = class_copyIvarList([property class], &varCount);
// Get the first one (out of an instance of this class)
// Of course you could just iterate and get each one
id var = object_getIvar(property, vars[0]);
// Free the array when you're done
free(vars);
This approach could simplify your conversion code:
id obj = [p valueForKey:[NSString stringWithUTF8String:ivar_getName(anIvar)]];
...
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.
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.
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
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