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)]];
...
Related
I have an Array comprised of further sub-Arrays
I want to display a summary of the contents of the sub-arrays into a TableView with the count of occurrences of each entry. I have determined that the best and easiest way is through a NSMutableDictionary as an intermediate step.
I declare the dictionary in my implementation
#implementation ReviewViewController
{
NSMutableDictionary *dict;
}
and down in my methods I initialise and use it like so:
dict = [NSMutableDictionary new];
[dict setObject:[Observation entryCount] forKey:[observedItem species]];
The swapping of key and object is deliberate as its the count I want. I'm using the fact that values are retained, but keys are overwritten, so if i swap them round i get the curation for free.
It works!, but every time the method is invoked, the Dictionary is clobbered by the re-initalization so I only get the last thing entered. Anywhere else and it falls out of scope.
if I pass it as an arguement in the method name instead, I get the message "Local declaration of 'dict' hides instance variable ". The code is already an irreducable set of parts, so
so, where is the correct place for the instantiation?
I'd love to make my contribution here as a meaningful thanks, but before I can do that I'm going to look silly with such questions.
You would usually initialise it in your init method. For a view controller this is usually the following:
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)bundle {
if ((self = [super initWithNibName:nibName bundle:bundle])) {
dict = [NSMutableDictionary new];
}
return self;
}
I don't understand what you mean by "Anywhere else and it falls out of scope.". It's an instance variable. It is therefore in scope in any method in the class.
By the way, I would name your instance variables with an underscore prefix, e.g. _dict. This is common convention and it helps you to remember when using it that it's an instance variable.
I have an iPhone application and I do this in my MyView1Controller:
MyView2Controller *myV2C = [[MyView2Controller alloc] initWithNibName:#"MyView2" bundle:nil];
myV2C.shareObject = self.shareObject;
[self.navigationController pushViewController:myV2C animated:YES];
[myV2C release];
So I push shareObject to the next ViewController. There, in viewDidLoad, I set a property of shareObject like this:
self.shareObject.myText = #"Test String";
So in MyView2Controller, everything is okay, the String is set. But going back to the previous MyView1Controller with the left upper "back" Button, the value of shareObject.myText is not set to Test String.
So, how can I do this? I want to give the View2Controller an object which can be modified, and the modifications I want to have in the View1Controller.
Does anyone know? Thank you in advance & Best Regards, Tim.
OR you can even try using the Singleton pattern
http://www.cocoadev.com/index.pl?SingletonDesignPattern
You can use delegation pattern and/or key value observations
EDIT:
You can achieve this my creating a single object, and then use that object in all classes, wherever you want. For this you can use singleton class, Or you can create a class method. For ex:If I have class A, and I want to push some values in B class, So if I modify the values in B, the newly updated value can be retrieved in a too, or in any other class. In that case, you can create a different class (usually subclass of NSObject),and then write the getter/settor methods in that.
Suppose the name of this newly created class is Manager, then in Manager. m create getter/setter methods, like
NSString *strGlobal;
+(void)setString:(NSString *)strTemp
{
if(!strGlobal)
{
strGlobal = [[NSString alloc] init];
}
//point to same location
strGlobal = strTemp;
}
+(NSString *)getMySavedString
{
return strGlobal;
}
Now In you class A , where you want to send the value to Class B controller, call the setter method to set the value, like: -
-(void)navigateto_ClassB
{
//Setting the value, that should be sent to the other controller
[ManagerClass setString:#"Hello"];
[self.navigationController pushViewController:[[[ClassB alloc]init] autorelease] animated:YES];
}
Now In class B (Or wherever you want to get the saved value, use getter method, like:-
NSString *strSavedValue = [ManagerClass getMySavedString];
No you will have the value, If you want to update the value from anywhere, the again call the setter method, with new value. For ex, i want to update the value in class B, then
[ManagerClass setString:#"Hello Upadted"];
Now this value is updated to same memory location, retrieve it from anywhere using getter method created in Manager class.
As I stated earlier, this is the easiest but not the best approach. Alternatively, you can achieve same functionality with delegate patterns, KVOs (Key value observations) and/or singleton class.
tia was right: "You did it right already, so there must be something wrong somewhere".
It was my fault, so the source code in my question is correct.
i'm in a bit of a situation here...
i am passing a string to a function and in that function i need to create an array whose name is the value of the string.
Say, for example: -(void) function : (NSString *) arrayName; //let arrayName = #"foo";
In this function I need to create an array named "foo" i.e the value of the passed parameter.
Can anyone help please :|
Thanks in advance ;)
Arrays don't have names. Variables have names, but variables are local to their scope, so once you leave the scope of that method, having a variable named "foo" is pointless; you can name the variable whatever you want and it will work just fine. Ex:
- (void) function:(id)whatever {
NSArray * myVariable = [NSArray arrayWithStuff....];
//use myVariable
}
What are you really trying to do?
That is not possible in Objective-C, but you can use e.g. a dictionary that maps a string to an array.
E.g. assuming something like the following property:
#property (readonly, retain) NSMutableDictionary *arrays;
... you can store an array by name:
- (void)function:(NSString *)arrayName {
NSArray *array = [NSArray arrayWithObjects:#"foo", #"bar", nil];
[self.arrays setObject:array forKey:arrayName];
}
... and access it like so:
NSArray *array = [self.arrays objectForKey:arrayName];
C is a compiled language where any source code names (for variables, functions, etc.) are not available at runtime (except for perhaps optionally debugging, -g). The Objective C runtime adds to this the ability to look up Obj C methods and classes by name, but not objects, nor any C stuff. So you're out of luck unless you build your own mini-language-interpreter structure for reference-by-name. Lots of ways to do this, but simple languages usually build some sort of variable table, something like a dictionary, array, or linked-list of objects (structs, tuples, etc.) containing string name, object pointer (maybe also type, size, etc.).
I'm facing some difficulty in retrieving properties of "id" type object. This is how I'm accessing it:
I'm doing following to assign an object to id type object from a generic array containing different types of objects and calling method "savedata" to which I'm passing the object as well as its type:
for(id objInArray in genericArray){
NSString *objType = [objInArray valueForKey:#"type"];
[objInArray retain];
[self saveData:objInArray :objType];
}
In savedata method I'm writing following code to retrieve the properties of id object:
-(void)saveData:(id)object :(NSString *)objectType
{
self.managedObjectContext = appDelegate.managedObjectContext;
if([objectType isEqualToString:#"event"])
{
Event * newEvent = (Event *)[NSEntityDescription
insertNewObjectForEntityForName:#"Event"
inManagedObjectContext:self.managedObjectContext];
[newEvent setEletitle:[NSString stringWithFormat:#"%#", [object valueForKey:#"eletitle"]]];
[self saveAction];
}
But the object "object" containing the values fails to assign them to object newEvent.
I also tried to retrive this value in a string object like this:
NSString *eletit = [object valueForKey:#"eletitle"];
[eletit retain];
But eletit is also invalid at the end of this transaction.
Can anybody please help? This' really urgent.
Thanx in advance.
I don't have you answer unfortunately but I have few comments on your code.
Are you sure it's normal you array contain so generics object? It's strange because all your object contained in your array need to respond to "type" or "eletitle" messages, so I guess objInArray is less generic than just "id".
Second, it's not recommended to have selector like saveData::, in Objective-C it's usual and recommended to name the arguments, it's more understandable.
I have use below syntax for for set the object.
[dict setObject:eventArray forKey:categoryName];
Now i am trying to get below syntax but i got nothing.
NSMutableArray *tempArrayValue=[[NSMutableArray alloc]init];
tempArrayValue =[tempDict valueForKey:categoryValue];
What is the problem i cant understand can u help me?
you have given key as categoryName not categoryValue, and while retrieving you are using categoryValue.
NSMutableArray *tempArrayValue=[[NSMutableArray alloc]init]; tempArrayValue =[tempDict valueForKey:categoryName];
If you're setting the value like this:
[dict setObject:eventArray forKey:categoryName];
Then you should be fetching it back again like this:
NSMutableArray* eventArray = [dict valueForKey:categoryName];
assuming that eventArray is of type NSMutableArray.
What you are doing has at least two different problems.
This line is a memory leak, since you allocate an object and then throw it away, so delete it:
NSMutableArray *tempArrayValue=[[NSMutableArray alloc]init];
This second line may return a nil object, if there is no object stored for the key categoryValue. (You are using an object called categoryName above, as the key to store the value):
tempArrayValue =[tempDict valueForKey:categoryValue];
You haven't posted enough code to be able to tell why it's not working otherwise.