I can write #42, which creates an NSNumber with int value 42. Can I do this with a variable, like #someIntVar? Obviously I tried it and it doesn't work (which sucks because then I have to go through [NSNumber numberWithInt:someIntVar]). Is it possible with a slightly different syntax?
I strongly suggest you read the official clang documentation on the matter: http://clang.llvm.org/docs/ObjectiveCLiterals.html
But, to box a variable, or any expression, you can use parentheses:
id num = #(someIntVar);
Related
I have been brushing up on my objective-c and one of the exercises that I am working on deals with UIInterpolatingMotionEffect objects. 2 properties from that class are minimumRelativeValue and maximumRelativeValue. In the exercise they have them as the following:
motionEffect.minimumRelativeValue = #(-25);
motionEffect.maximumRelativeValue = #(25);
I know that in obj-c you use # for the following (from wikipedia):
Used to avoid taking english words and making them reserved (for example, you can't have a variable called float in C/Objective-C because this is a reserved word).
With that being said, what would be the difference between using #(-25) and (-25) in the above example?
25 is a number. #(25) is an NSNumber object with value 25. It is equal to
[NSNumber numberWithInt:25];
In some cases you have to wrap numbers with NSNumber. For example you can not add number to NSArray / NSMutableArray.
You may read more about Objective C literals here https://www.mikeash.com/pyblog/friday-qa-2012-06-22-objective-c-literals.html
(-25) is just -25 with brackets around. You can add backets to lots of numerical or logical expessions without (or sometimes with) changing its value.
The # is one of the object creation shortcuts in objective-c. In this case it is equivalent to #-25 (Frankly, I am not sure whether there needs to be the brackets here because of the minus) which is equivalent to [NSNumber numberWithInt:-25].
See more of them here: http://clang.llvm.org/docs/ObjectiveCLiterals.html
For example,
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
[rotate setToValue:#(M_PI)];
[rotate setDuration:0.1f];
[[aView layer] addAnimation:rotate forKey:#"myRotationAnimation"];
where M_PI is defined as a macro in math.h,
#define M_PI 3.14159265358979323846264338327950288 /* pi */
It's a pointer to an NSNumber object. It's called a boxed literal, because the mental picture is of putting a primitive value of expression inside into a "box", that is, an object.
See official documentation if in doubt. Note that pointer can be to a "real" NSNumber object or it can (theoretically, don't know whether this will work in practice) be a tagged pointer (see, e.g., my question).
Note that you can also do things like #"string" and #5, which will create constants in compile time. But you need parentheses to use something which is not a literal, e.g. #(2 + 3). Parentheses form can be used for any expression, even those that compiler cannot compute at compile-time (although if it can, it will just put an expression result into code).
NeXT and Apple Obj-C runtimes have long included a short-form way to create new strings, using the literal syntax #"a new string". Using this format saves the programmer from having to use the longer initWithString or similar methods when doing certain operations.
When using Apple LLVM compiler 4.0 or later, arrays, dictionaries, and numbers (NSArray, NSDictionary, NSNumber classes) can also be created using literal syntax instead of methods. Literal syntax uses the # symbol combined with [], {}, (), to create the classes mentioned above, respectively.
So, basically it's not only for id or NSNumber object!
thanks to wiki.
It's Shorthand writing
In Objective-C, any character, numeric or boolean literal prefixed with the '#' character will evaluate to a pointer to an NSNumber object (In this case), initialized with that value. C’s type suffixes may be used to control the size of numeric literals.
'#' is used a lot in the objective-C world. It is mostly used to avoid taking english words and making them reserved (for example, you can't have a variable called float in C/Objective-C because this is a reserved word).
Use this link To have detailed knowledge of '#' symbol.
In Modern Objective C, '#' symbol is used extensively.
What You can do with it:
calculate an expression: #(<Expression>)
wrap any value like int,bool,float,char in same way
Reasons to use:
Easy to write, Less code required
Less chances of mistakes. Compare [NSNumber numberWithInt:3] with #3.
Get rid of typecasting issues in simple cases.
It represent id Object
that you can use any expression in it or return any object.
Syntax : #(<#expression#>) it will return id object.
So in your case it will returning NSNumber object to setToValue method.
This is great:
NSArray *myArray = #[0, M_PI];
NSDictionary *myDict = #{#"item":anItem, #"another":somethingElse};
//etc.
But this is tedious:
[baseline moveToPoint:NSPointFromCGPoint(CGPointMake(0, baselinePosition))];
[baseline lineToPoint:NSPointFromCGPoint(CGPointMake(self.bounds.size.width, baselinePosition))];
Is there anything like #(0, 0) to simplify writing a point literal in code?
C99 compound literals to the rescue:
(CGPoint){ 0, 0 }
or
(NSPoint){ 0, 0 }
As H2CO3 points out, you can just cast a literal - this is plain old C, and NSPoints and CGPoints are just C structs. nothing fancy here.
As a consequence, there is no Objective-C shortcut, modern or otherwise, but there is an old macro which will save you a few keystrokes compared to the sequence you came up with:
NSMakePoint(self.bounds.size.width, baselinePosition)
You'll notice that the old macros and various constants used in the Cocoa API follow a natural English word order:
NSMakeRect(), NSMakeRange(), etc.
and for the options (e.g., in NSString)
NSAnchoredSearch, NSNumericSearch, NSCaseInsensitiveSearch, etc.
The concept that these options have in common ("search") is added to the end of the symbol name, as was the convention when the NSString class was designed.
The more modern APIs use a naming convention so names that belong to the same "group" begin with the same word(s). This makes it easier to alphabetize and greatly helps the autocomplete suggest the possible options for a parameter value. You can see this in NSOperation, for instance.
Huge proponent of using the 'var' keyword in C# for cases where it's very clear. For instance, rather than this...
ThisIsMyReallyLongFooClassName foo = new ThisIsMyReallyLongFooClassName();
I can type this...
var foo = new ThisIsMyReallyLongFooClassName();
...and I still have a strongly-typed variable. The two are, for all intents and purposes, equal. The latter is just more readable (again, because it's clear. There are cases where it isn't and 'var' shouldn't be used. I don't want this to become a discussion of that however.)
I'm wondering if Objective-C has anything similar.
Yes and no.
You can use id foo = ... which will always work, but you lose the type information.
If you really want something equivalent, you could use auto foo = ... from C++11, but then you have to compile your file as Objective-C++, which has many other side effects.
Convention is to just spell out your types; it's annoying, but unlike C++, C#, Java where templates/generics can make typenames very long, it's usually manageable in Objective-C.
There is now, __auto_type. For example...
__auto_type test = #"Hello World";
...results in test having the type NSString*.
Here's a decent writeup:
https://medium.com/#maicki/type-inference-with-auto-type-55a38ef56372
The author suggests using
#define let __auto_type const
#define var __auto_type
in some shared header in your application to make the usage cleaner. I'm a bit wary of this kind of macro usage personally but I've been doing it for a while and the world is still turning... Maybe macro names less likely to cause a collision would be better.
No, there is no equivalent in Objective C. C++11 introduced the auto keyword to do it, but neither C nor Objective C has a similar capability.
The id is closest to C#'s dynamic keyword. It lets you achieve similar results to var, except that it does not let you access properties using the property syntax. It does let you invoke methods, including methods that implement property accessors.
You can do something like this:
__typeof([obj someMethod]) foo = [obj someMethod];
That's ugly, but if you have a snippet or macro defined to automatically generate it, then you don't have to type out the type names. For example:
#define LET(V, EXPR) __typeof(EXPR) V = (EXPR)
LET(vc, self.viewController); // equivalent to "UIViewController* vc = self.viewController;"
LET(d, [number doubleValue]); // equivalent to "double d = [number doubleValue];"
LET(foo, [[Foo alloc] init]); // equivalent to "Foo *foo = [[Foo alloc] init];"
Note: I'm not recommending this approach, as the convention in Objective-C is to write out the full type names or use id, and macros can be messy. But knowing about __typeof() can be handy.
There is the id keyword in Objective-C, but note that it is equivalent to the dynamic keyword in C# and not the var keyword. var is implicit typing - ie the type is inferred, but it is still static typing. dynamic and id are for dynamic typing and you lose type information.
I am afraid that no such equivalent exists in Objective C which would allow you to preserve strong typing.
You can use id keyword in objective C, but it doesn't work as c#
in c#
var stringVar = ...
stringVar worked as string variable and you can use access the string function by doing stringVar.function
id stringVar = [NSString ...]
but it still work as normal id type.
Total newbie question but this is driving me mad!
I'm trying this:
myInt = [myFloat integerValue];
but I get an error saying essentially integerValue doesn't work on floats.
How do I do it?
I'm pretty sure C-style casting syntax works in Objective C, so try that, too:
int myInt = (int) myFloat;
It might silence a compiler warning, at least.
what's wrong with:
int myInt = myFloat;
bear in mind this'll use the default rounding rule, which is towards zero (i.e. -3.9f becomes -3)
int myInt = (int) myFloat;
Worked fine for me.
int myInt = [[NSNumber numberWithFloat:myFloat] intValue];
Well, that is one option. If you like the detour, I could think of some using NSString.
Why easy, when there is a complicated alternative? :)
You can also use C's lroundf(myFloat).
An incredibly useful tip: In Xcode's editor, type your code as say
myInt = roundf(someFloat);
then control/right-click on roundf and Jump to definition (or simply command-click).
You will then clearly see the very long list of the functions available to you. (It's impossible to remember them all, so just use this trick.)
For example, in the example at hand it's likely that lrintf is what you want.
A further tip: to get documentation on those many functions. In your Terminal.app (or any shell - nothing to do with Xcode, just the normal Terminal.app) simply type man lrintf and it will give you full info. Hope it helps someone.
In support of unwind, remember that Objective-C is a superset of C, rather than a completely new language.
Anything you can do in regular old ANSI C can be done in Objective-C.
Here's a more terse approach that was introduced in 2012:
myInt = #(myFloat).intValue;