Is it possible to make a variable dynamic? [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

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.

Using sortUsingSelector on an NSMutableArray

I have used sortUsingSelector to sort an NSMutableArray of custom objects.
Now I'm trying to sort an NSMutableArray containing NSMutableArrays of custom objects.
Can you use sortUsingSelector on an NSMutableArray, or does it only work for custom classes?
If you can use blocks, the most straightforward way using sortUsingComparator:. Otherwise, you'll need to use sortUsingFunction:.
In either case, you are going to need to write a custom block or function that takes two arrays as arguments and returns a sort order based on their contents (I'm not sure what logic you are using to determine if array A or array B is "before" or "after" the other).
You'd do something like:
static NSInteger MySorterFunc(id leftArray, id rightArray, void *context) {
... return ascending/descending/same based on leftArray vs. rightArray ...
}
Then:
[myArrayOfArrays sortUsingFunction: MySorterFunc context: NULL];
It sends the selector to the objects, so you'll need to use one of the other sorters. Probably sortUsingFunction:context:.
Of course you can also use sortUsingSelector:, it really doesn’t matter whats the object in your array as long as it responds to the selector you want to use. But NSMutableArray and NSArray don’t have any comparison methods themselves, so you’d have to extend them using a category to implement your compare method.
So you probably want to use the other sorting methods pointed out in the other answers here. It’s not impossible to use sortUsingSelector: but it is rather inconvenient and most people (including me) would argue that it’s bad style to write a category for that.

Objective C Equivalent of PHP's "Variable Variables" [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:.