Objective C Equivalent of PHP's "Variable Variables" [duplicate] - objective-c

This question already has an answer here:
Using a string as name to set property values
(1 answer)
Closed 6 years ago.
In PHP and in JavaScript you can dynamically use a variable by using another variable as part of its name. I do not want to use an array as part of the solution. Can this be achieved in Objective C? I'd like to do something like this:
for (int i=1; i<6; i++) {
if([appRecord.answer(i) length] != 0){
self.textView.answer(i)ViewSingle.text = appRecord.answer(i);
}
}

Short answer: No.
Long answer: Kind of.
You can use an array, store your variables in there, and index into it.
Like #1, if your objects are actually UI elements and you don't want a whole bunch of IBOutlets, then use an IBOutletCollection instead.
You can use a dictionary, store your variables as values, and look them up by key.
You can declare all your variables as #property, and then use [self valueForKey:] to look them up by name.
You can build the name of the ivar as a string, and then use something like object_getInstanceVariable() to retrieve it's value directly (this is similar to #3, except you don't have to declare it as an #property). This is excessively complicated and is usually a much bigger hammer than you'll actually need.
If you're dealing with views, you can assign each view a unique tag and then retrieve it via [superview viewWithTag:aTag]. I do not recommend using this approach.
EDIT: Note that this only works with instance variables. This does not work with global/static variables.

No. But you can give a tag to the view and use -viewWithTag:.

Related

Is it possible to make a variable dynamic? [duplicate]

This question already has an answer here:
Using a string as name to set property values
(1 answer)
Closed 6 years ago.
In PHP and in JavaScript you can dynamically use a variable by using another variable as part of its name. I do not want to use an array as part of the solution. Can this be achieved in Objective C? I'd like to do something like this:
for (int i=1; i<6; i++) {
if([appRecord.answer(i) length] != 0){
self.textView.answer(i)ViewSingle.text = appRecord.answer(i);
}
}
Short answer: No.
Long answer: Kind of.
You can use an array, store your variables in there, and index into it.
Like #1, if your objects are actually UI elements and you don't want a whole bunch of IBOutlets, then use an IBOutletCollection instead.
You can use a dictionary, store your variables as values, and look them up by key.
You can declare all your variables as #property, and then use [self valueForKey:] to look them up by name.
You can build the name of the ivar as a string, and then use something like object_getInstanceVariable() to retrieve it's value directly (this is similar to #3, except you don't have to declare it as an #property). This is excessively complicated and is usually a much bigger hammer than you'll actually need.
If you're dealing with views, you can assign each view a unique tag and then retrieve it via [superview viewWithTag:aTag]. I do not recommend using this approach.
EDIT: Note that this only works with instance variables. This does not work with global/static variables.
No. But you can give a tag to the view and use -viewWithTag:.

Can I access an ObjC constant by string name at runtime? [duplicate]

This question already has an answer here:
How do I lookup a string constant at runtime in Objective-C?
(1 answer)
Closed 7 years ago.
I know that Objective-C allows me to refer to selectors by name using #selector(#"name") How can I access the following constant by name at runtime? In other words, I would pass #"CONST_KEY" somewhere and get #"key" back.
const NSString* CONST_KEY = #"key";
I think I can do this by first creating a key-value dictionary and then querying it at runtime, but I'm not sure if there's a better implementation.
To clarify with a specific use case:
I want to use a collection view cell reuse identifier #"CONST_KEY", declared in my storyboard, and to be able to use this identifier to look up the value of CONST_KEY at runtime.
This way I hope to have a single place within my code to modify constants, rather than having to re-assign values in multiple classes. Having the two values linked will allow me to have a single action for all those cells using the CONST_KEY to define the action they are going to do.
Objective C is just a C with added object functionality. So "CONST_KEY" constant name is discarded during compilation. So you have to create your own class or use an NSDictionary to provide "constant_name"->"constant_value" functionality.
You don't need to call a selector to get the constant, you just need to expose it to your other classes. Also the constant should live inside of its relevant class. The method I use is the following.
in the header file right below your import statements (before #interface) declare this:
extern NSString *const CONST_KEY;
In the implementation file in the same place (above #interface and #implementation) declare this:
NSString *const CONST_KEY = #"key";
After you do that, in any class that imports the class where you declared your constant, you will be able to reference it simply with CONST_KEY
E.G.
[someDictionary objectForKey: CONST_KEY];
or
NSLog(#"%#", CONST_KEY);
etc etc – Using this convention is great for type safety. I use it all the time.

Accessing variables with related names in a for loop [duplicate]

This question already has an answer here:
Syntax help - Variable as object name [duplicate]
(1 answer)
Closed 8 years ago.
I have three NSRects in separate variables named rect1, rect2, and rect3, and I want to increment each one's origin.x by 10.
I thought a for-loop would be good for this, but I don't know how I can do it.
This is an example of how I want it to work:
for(int i=0, i<3, i++) {
rect[i].origin.x +=10
}
but this exact code gives an error
property "rect" not found on object of type "graphics"
Is there a way to code it like in my example?
Is there a way to increment a variable with for loop
Not in objective-c for sure. You cannot declare variables in 0-n format and loop through it.
If you create an array out of your NSRect variables then you can loop through the array and modify properties.
Note: NSArray can only hold Objects not primitives, you might find this handy

How to access a property/variable using a String holding its name

If I had two variables in Objective C like this where one holds the name of the other as a string
NSInteger result = 4;
NSString * theName = #"result";
How would I best access the first variable using the string instead of a reference to the variable? For instance if I had a lot of variables and would generate the name of the one I need by code I'd need a way to get to the variable using that string.
Though not directly answering your question, it's possible to access properties (or ivars) of an object by
[object setValue:#"value" forKey:theName]
Similarly, the getter is [object valueForKey:theName] (thanks kevboh!)
That's not possible in objective-c. Variable names cannot be synthesised by name. The variable name itself doesn't mean anything when running your code, the compiler converts it into a memory address. The name is just a way for the programmer to make writing and reading code easier.
Depends on your exact situation but you probably should be using an NSArray or NSDictionary.

Access objects of a specific type using for-in loop in Objective C [duplicate]

This question already has answers here:
Fast Enumeration on NSArray of Different Types
(5 answers)
Closed 8 years ago.
I am running a for-in loop over an NSMutableArray. There are instances of Class A in the array also out of those some are actually instances of its subclass B.
So If I only want members of subclass B, I am checking the class of each object I get in an if condition inside the loop body.
Is it possible that instead of writing something like this,
for(A* obj in collection){
if([obj isKindOfClass:[B class]]){
//take some action.
}
}
I can do something like this?
for(B* obj in collection){
//take some action.
}
Will I get the same result?
To my knowledge: no.
The for each loop will traverse every object in the collection, and I don't think you can specify that you only want to traverse a specific type.
To be clearer: The Object you specify: for (MyObject* obj){..} is a type-cast. So you're telling the object in the collection that they should be/behave as MyObject
Can I do something like this...
No, you can't use the type of the index variable in fast enumeration to select only some of the objects in the collection. If the collection contains different types of objects, you'll have to test each object first. Instead of testing class membership, though, it's often nicer to test for the behavior you're looking for with -respondsToSelector: or -conformsToProtocol instead of -isKindOfClass:.