I want to set the name of a variable to the value of another variable are there any other ways to do this because I don't think this is the way.
NSString *myint = #"a";
NSString *([NSString stringWithFormat:#"%#", myint]) = #"something";
NSLog(#"%#", a);
No, you can't do that. Once your code is compiled, your variables don't really have names -- just locations. The names you see in the debugger are provided by a symbol file which the debugger uses to map locations to names.
Key-value coding could help, depending on what you're really trying to accomplish. With KVC, you use key names to refer to values rather than accessing variables, much as you do with a dictionary. For example, if you have an object with properties foo and bar, you can then do something like this:
NSString *key = #"foo";
[myObject setValue:#(5) forKey:key];
You could even override -setValue:forKey: so that it accepts any key and remembers the value (which is exactly what a dictionary does).
You can go in the other direction (set a variable to the name of another variable) using the stringification operator, but it's kinda hacky and not usually all that useful. In a nutshell, macro parameters prefixed with a # are used as literal strings instead of being evaluated. So you'd create a macro like this:
#define string(x) #x
and then you'd use it somewhere in your code like this:
int foo = 5;
NSLog("The name of the variable is %s and its value is %d.", string(foo), foo);
with the following result:
The name of the variable is foo and its value is 5.
I agree with Paulw11. You could define a NSMutableDictionary to hold all your variables by key. I don't think there is any way the compiler can use a handle determined at runtime. But you can achieve the same affect.
So say, for instance, that both the variable handle and value were NSString, then you could do something like this.
NSMutableDictionary *myObjects = [[NSMutableDictionary dictionary] init];
NSString variableName = #"myString";
[myObjects setObject #"Variable value" forKey: variableName];
NSLog("Variable %# has value %#.", variableName, [myObjects objectForKey: variableName]);
Related
I am creating an NSMutableDictionary and assigning an NSString (test and test1) to a parameter key.
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
if (test.length) {
dictionary[#"test"] = test;
}
if (test1.length) {
dictionary[#"test1"] = test1;
}
This method does work. However, I am going to eventually have more strings and don't want a bunch of if statements. I don't want the dictionary keys to exist if the string is empty or nil.
Not sure if there is a way around this.
I thought about creating a separate function that accepts an array of key string and array of string values and use a for loop to see if string value is empty. Then, return a dictionary once the for loop ends. However, you can't insert nil into an NSArray
Something like this
- (void)updateDic:(NSMutableDictionary *)dic withString:(NSString *)str {
if (!str || [str isEqualToString:#""]) {
return;
}
dic[str] = str;
}
And then just iterate over all strings and use that method.
What I'd do is create a NSMutableDictionary category, something like this:
NSMutableDictionary+CustomMethods.m:
- (void)setStringIfNotNil:(NSString *)string forKey:(id <NSCopying>)key {
if (!string || !string.length) { return; }
self[key] = string;
}
Then you can use it like this:
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setStringIfNotNil:test forKey:#"test"]
[dictionary setStringIfNotNil:test1 forKey:#"test1"]
There are three ways according to me..
The first one use the category in which you have to write if condition only single time and you can use it in any class of your project.
Second one by making a separate method to do that task(to check string nil or not and adding into the dictionary).
And the third one , just add all in an array and and perform the action in a loop.
The syntax:
dictionary[#"test"] = test
will remove the value from the dictionary if test is nil (it's a difference between the normal -setObject:forKey: method and the -setObject:forKeyedSubcript: which that syntax invokes). However, that will not work for empty strings.
As mentioned in another answer, you could make an NSDictionary category method to check, then call that method instead.
You could also just use the regular dictionary[key] = value syntax, then when you are done, do:
[dictionary removeObjectsForKeys:[dictionary allKeysForObject:#""]];
If it's possible to have the keys repeated, and you don't want an empty string overriding an earlier valid valid, you would have to check each time -- either by the category method, or using a local macro or inline function or local method.
static inline void SetValidVal(NSMutableDictionary *dictionary, NSString *key, NSString *val) {
if (val.length) { dictionary[key] = val; }
}
or
#define MY_SET_VALID_VAL(dictionary, key, val) if ((val).length) dictionary[key] = (val)
If the key names need to be the same as the name of the local variable, you can play other games with macros (this also assumes the local variable name "dictionary":
#define MY_UPDATE_VAL(val) if (val.length) dictionary[##val] = (val)
Then MY_UPDATE_VAL(test1); would expand to:
if (test1.length) dictionary[#"test1"] = test1;
That's a bit magic though and probably not recommended.
Consider,
NSString *myString = #"Welcome";
NSLog(#"%#",myString);
will print Welcome in console.
Can I print the string like "myString: Welcome"?
I mean, can I get the object name("myString") along with object value("Welcome")?
Use the following code:
#define stringVariable(x) NSLog( #"%s:%#",#x, x)
NSString *myString=#"Welcome";
stringVariable(myString);
Note: The general principle is that when you put a # in front of an argument within the body of a #define, the preprocessor replaces it with a C string of the exact expression passed to the macro. When you pass a variable name, you'll get that name.
When I do an operation like this:
self.slider.value = randomArray[0][0];
I would like to be able to do this:
self.slider.value = randomArray[randomVariable][0];
Basically, how do you put that "randomVariable" in the brackets? When I try to do this on Xcode, I get:
Code: self.detail1.text = detailsForNotesUse[x][0];
Error:Expected Method to read dictionary element not found in object
of type 'NSArray *'
The variable I put in the brackets is NSString, the array is NSArray, and detail1 is a text field.
Declarations:
NSString *x = 0;
NSArray *detailsForNotesUse;
You've defined x as an NSString. You should define your index variable like this:
NSUInteger x = 0;
I'm just reposting the answer I gave in my comment below the question:
x needs to be an int if you're using it as an index. ex. int x = 0;
But I'm also writing to note that many of the answers are misleading. You can in fact access a nested array in this way, i.e. randomArray[x][y];, because if randomArray[x] returns an array (as is syntactically valid in obj-c), the items of that array can then be similarly accessed by appending [y] (though you may have to cast randomArray[x] to an NSArray to prevent a warning).
I have created an enum in my header file that looks like this
typedef enum {stTMD = 1, stT2MD = 2, stDCMD = 'D', stMBMD = 'M'} stTypes;
First off I am not even sure if thats the correct way to declare a char in an enum but
As you can see some values are integers and others are chars. However I am getting the following error when I try to place these values into a NSDicitonary like this
NSDictionary *iCTypes = [[NSDictionary alloc] initWithObjectsAndKeys:stDCMD,#"stMB", stMBMD,#"stMBMD", nil];
but I am getting this error below
Implicit conversion of 'int' to 'id' is disallowed with ARC
any help would be greatly appreciated.
An enum is basically an int type. Your enum definition is just fine. The problem is your use in the dictionary. You need to wrap the enum values in an NSNumber.
Try:
NSDictionary *iCTypes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:stDCMD], #"stMB", [NSNumber numberWithInt:stMBMD] ,#"stMBMD", nil];
or even better (using modern Objective-C):
NSDictionary *icTypes = #{ #(stDCMD) : #"stMB", #(stMBMD) : #"stMBMD" };
You need to store objects inside it, so you can't store an int, rather a NSNumber, which can be made by appending a # before the number constant:
NSDictionary *iCTypes = [[NSDictionary alloc] initWithObjectsAndKeys: #(stDCMD),#"stMB", #(stMBMD),#"stMBMD", nil];
However a clarification is needed on this:
First off I am not even sure if thats the correct way to declare a char in an enum but As you can see some values are integers and others are chars.
When you define an enum it stores integers, it doesn't matter if you set chars as values, they're compatible with int so the compiler will not complain. But the storage type is the same, they're still integers and any type compatible with integers will be accepted.
Both the objects and keys in an NSDictionary must be objects, and the keys specifically must be objects that conform to NSCopying. In order to use ints in an NSDictionary, you have to convert them to NSNumbers. You can use either [NSNumber numberWithInt:stDCMD] or, if you're using a newer version of Xcode, #(stDCMD).
In C char is a kind of short int.
enum can only hold integer types.
NSDictionary cannot hold C types. Only objects.
You can wrap your C types in NSValue or NSNumber to put in an NSDictionary.
So I have a basic array:
NSMutableArray *answerButtonsArrayWithURL = [NSMutableArray arrayWithObjects:self.playView.coverURL1, self.playView.coverURL2, self.playView.coverURL3, self.playView.coverURL4, nil];
The objects inside are strings. I want to access a random object from that array
int rndValueForURLS = arc4random() % 3;
and assigning it a value. I've tried manny different approaches but my recent one is
[[answerButtonsArrayWithURL objectAtIndex:rndValueForURLS] stringByAppendingString:[self.coverFromRightAnswer objectAtIndex:self.rndValueForQuestions]];
Any help will be much appreciated. Thanks
You need to assign it. You're already building the new value like that:
NSString *oldValue = answerButtonsArrayWithURL[rndValueForURLS];
NSString *newValue = [oldValue stringByAppendingString:[self.coverFromRightAnswer objectAtIndex:self.rndValueForQuestions]];
The part you're missing :
answerButtonsArrayWithURL[rndValueForURLS] = newValue;
Above would be the way to replace the immutable string with another. If the strings are mutable, that is, they were created as NSMutableString, you could do:
NSMutableString *value = answerButtonsArrayWithURL[rndValueForURLS];
[value appendString:[self.coverFromRightAnswer objectAtIndex:self.rndValueForQuestions]];
Note:
Everywhere I replace the notation :
[answerButtonsArrayWithURL objectAtIndex:rndValueForURLS];
with the new equivalent and IMO more readable:
answerButtonsArrayWithURL[rndValueForURLS];