0

A fairly common pattern is: if some object exists, I want to use that object in my code, but if it is not set, I want to fail over to some default value.

Using a background image as an example, and assuming some UIImage *backgroundImage property that may or may not be set when this code is evaluated, the verbose way to do this might be:

UIImage *image;
if (self.backgroundImage) {
    image = self.backgroundImage;
} else {
    image = [UIImage imageNamed:@"default"];
}

A more compact method is:

UIImage *image = (self.backgroundImage) ? self.backgroundImage : [UIImage imageNamed:@"default"];

My question is: is there an even more short-hand way to accomplish this?

Something like:

UIImage *image = self.backgroundImage || [UIImage imageNamed:@"default"];

I can't find anything in the Clang Literals documentation, but this sort of short-hand may not actually be considered a 'Literal', or even be part of Clang for that matter.

(I'm also unsure where the "(truth statement) ? id1 : id2" syntax is documented for Clang/LLVM; knowing where the exhaustive set of those short-hand statements are would also be grand!)

toblerpwn
  • 5,415
  • 8
  • 38
  • 46
  • Clang/LLVM does not "document" stuff that is part of standard C. Read Kernighan and Ritchie! – matt May 10 '14 at 22:21

3 Answers3

7
UIImage *image = (self.backgroundImage) ? self.backgroundImage : [UIImage imageNamed:@"default"];

My question is: is there an even more short-hand way to accomplish this?

Yes; just omit the middle term:

UIImage *image = self.backgroundImage ? : [UIImage imageNamed:@"default"];

Documented here.

And in Swift there is now the ?? operator which does just what the ?: operator does in Objective-C.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 2
    In case it's not clear from the link: this is a gcc language extension that is also supported by clang. – rob mayoff May 10 '14 at 22:27
  • Cool, I did not know about that variant of the trinomial operator. Thanks for sharing. (voted.) I gather it's not standard C however? – Duncan C May 10 '14 at 22:49
  • Unfortunately not every gcc extension is picked up by clang... @robmayoff do you know how to find out which ones are and which ones are not? – matt May 11 '14 at 00:12
  • I believe it is part of C11 which is why clang supports it. – uchuugaka May 11 '14 at 00:36
  • It supports [“a broad range of GCC extensions”](http://clang.llvm.org/docs/LanguageExtensions.html). – rob mayoff May 11 '14 at 02:08
  • Unfortunately it is not part of C11. See [N1570](http://open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) §6.5.15. – rob mayoff May 11 '14 at 02:12
  • @robmayoff Unfortunately clang does not support some of my favorites in that "broad range of GCC extensions" (such as [this one](http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html#Nested-Functions)) - I wish they were more explicit about exactly which ones are supported. – matt May 11 '14 at 02:41
0

Absolutely the most short way in this case is:

UIImage *image;
if (!(image = self.backgroundImage)) image = [UIImage imageNamed:@"default"];

The if statement check if is self.backgroundImage is nil, and in the same time assign it to image. If is nil, assign the new object to image.

Matteo Gobbi
  • 17,697
  • 3
  • 27
  • 41
0

I recently discovered that there is a GNU extension to C that allows omitting the second operand of the conditional operator (ternary if):

UIImage *image = self.backgroundImage ?: [UIImage imageNamed:@"default"];

https://stackoverflow.com/a/3319144/3617012

Community
  • 1
  • 1
iOSX
  • 1,270
  • 13
  • 18