Swift String format vs Objective-C - objective-c

I am using swift String(format:...) and need to compute values in the format string itself using ternary operator, something like this but it doesn't compiles.
String(format: "Audio: \(numChannels>1?"Stereo": "Mono")")
In Objective-C, I could do like this:
[NSString stringWithFormat:#"Audio: %#", numChannels > 1 ? #"Stereo" : #"Mono"];
How do I achieve the same elegance in Swift without having an intermediate variable?

Due to the missing spaces around the operators in the conditional expression, the compiler misinterprets 1?"Stereo" as optional chaining. It should be
String(format: "Audio: \(numChannels>1 ? "Stereo" : "Mono")")
instead. However, since the format string has no placeholders at all, this is equivalent to
"Audio: \(numChannels > 1 ? "Stereo" : "Mono")"

One option is to use String(format:) with a placeholder and the conditional expression as the parameter for the placeholder
String(format: "Audio = %#", numChannels > 1 ? "Stereo" : "Mono")

Related

How do I use conditionals (e.g. ternary operator) in an NSExpression?

I'm using an NSExpression to evaluate simple strings such as:
NSExpression(format: "1 + 1").expressionValue(with: nil, context: nil) as? Int == 2
Some of my strings have more complex logic, and I'd like to use a ternary operator. I tried using the traditional ?: syntax, but I get an error:
NSExpression(format: "1 + 1 == 2 ? 'YES' : 'NO'").expressionValue(with: nil, context: nil)
terminating with uncaught exception of type NSException
Is there a way to use a ternary operator assuming the only thing I can change is the string?
Yes. I'm not sure where the documentation lives, but I found some obscure references to a TERNARY function. If you try it out within an NSExpression, it works:
NSExpression(format: "TERNARY(1 + 1 == 2, 'YES', 'NO')").expressionValue(with: nil, context: nil) as? String == "YES"
It looks like the format is:
TERNARY(<predicate>, <trueValue>, <falseValue>)
If you don't want to rely on an (apparently) undocumented expression format then you can create a conditional expression using the
init(forConditional:trueExpression:falseExpression:)
constructor (documentation). Example:
let expr = NSExpression(forConditional: NSPredicate(format: "1 + 1 == 2"),
trueExpression: NSExpression(forConstantValue: "YES"),
falseExpression: NSExpression(forConstantValue: "NO"))

conditional statement with expression language that is not ternary

I need to make an expression language conditional statement with a few conditions to check. Googling I can only find examples using ternary
#{SomeBean.someProperty ? 'bob' : 'John'}
I need to have more conditions though. I need something like:
If (SomeBean.someProperty == 'a'){
//Ant
}
Else if (SomeBean.someProperty == 'b'){
//Bob
}
Else if (SomeBean.someProperty == 'c'){
//C++
}
Else{
//Back to the drawing board, something went wrong.
}
How can I write this in expression language?
Just the same syntax as in plain Java.
#{bean.property eq 'a' ? 'Ant' : bean.property eq 'b' ? 'Bob' : bean.property eq 'c' ? 'C++' : null}
Do note that property is assumed to be String or enum and not char because a char is interpreted the same way as numbers in EL. See also How to compare a char property in EL.

Ternary operator error - "Expected expression"

I haven't used the ternary operator much and I'm getting an error on this:
(isInitializing) ? (return YES) : (isInitializing = 1);
Error is: "Expected Expression" and it's pointing to return YES.
Don't use the Ternary Operator to "do stuff" but to return one of two values.
So this is a valid case:
NSString *something = (isInitializing ? #"value a" : #"value b");
In your case, you might want to do this instead:
if (isInitializing) {
return YES;
} else {
isInitializing = 1;
}
The ternary operator is used to return one of two values depending on a condition. It is not so much used to execute statements, hence the return is a bit of a problem. I would rather use an if when you do not want to distinguish values, but rather have two different execution paths.

java.text.DecimalFormat equivalent in Objective C

In java, I have
String snumber = null;
String mask = "000000000000";
DecimalFormat df = new DecimalFormat(mask);
snumber = df.format(number); //'number' is of type 'long' passed to a function
//which has this code in it
I am not aware of the DecimalFormat operations in java and so finding it hard to write an equivalent Obj C code.
How can I achieve this? Any help would be appreciated.
For that particular case you can use some C-style magic inside Objective-C:
long number = 123;
int desiredLength = 10;
NSString *format = [NSString stringWithFormat:#"%%0%dd", desiredLength];
NSString *snumber = [NSString stringWithFormat:format, number];
Result is 0000000123.
Format here will be %010d.
10d means that you'll have 10 spots for number aligned to right.0 at the beginning causes that all "empty" spots will be filled with 0.
If number is shorter than desiredLength, it is formatted just as it is (without leading zeros).
Of course, above code is valid only when you want to have numbers with specified length with gaps filled by zeros.
For other scenarios you could e.g. write own custom class which would use appropriate printf/NSLog formats to produce strings formatted as you wish.
In Objective-C, instead of using DecimalFormat "masks", you have to live with string formats.

What is the equivalent of else do nothing using the conditional operator?

I want to know what is the equivalent of this if statement:
if (condition) {
// do something
}else{
// do nothing
}
Using the conditional operator:
(condition) ? // [do nothing] : {do nothing} "
It's not possible to "do nothing" using the conditional operator. You always have to have valid expressions on both sides, although both expressions can be casted to void.
This is one of the dis-advantage of ternary operator ( ?: ).
It needs expressions in all the three places. You cant skip any of them.
You can do some tweak on it, however its True-part and / or False-part can be assigned to the same as :
int big=100;
big= (10 > 100) ? 0 : big;
if (!condition) {
// do something
}else{
// do nothing
}
Take a look at the !before contition now :-)
The ! before the condition just switches the "if", to "if not"...
Is that what you have been searching for?
originalValue = (condition) ? newValue : originalValue
The compiler should then remove the unnecessary assign of originalValue to itself.
GCC had an extension to do give you something more to what you where looking for, something like
originalValue = condition ?: newValue;
So it may be available in clang also. You would have to ! the condition though.
you could do something like this
someBool ? [self someFunction] : (^{})(); //empty block
In normal code the answer is there is no equivalent - all sub expressions of an expression must have a value, but...
the following is not a recommendation
Something along the lines of the following should work in the general case:
condition ? ( (^{ do something })(), 0 ) : 0;
That is for the general case. If do something is a single, non-compound, statement; such as a method call; then the block can be dropped to give:
condition ? (do something, 0) : 0;
Again this is NOT recommended in real code!