IOS macros issues - ios

I have a small issues with macros
I have the following macro declared on project-Prefix.pch file
#define IS_IOS7_AND_UP ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0)
and I have a macrofile.h which contain the following code, but when I compile I got error "Invalid token at start of a preprocessor expression"
#if (IS_IOS7_AND_UP>0) //error-> "Invalid token at start of a preprocessor expression"
#define CELL_CONTENT_WIDTH 320.0f
#else
#define CELL_CONTENT_WIDTH 300.0f
#endif
Can you please tell me what's wrong about this, actually I need this to be a macro which prevent me of changing many files.

There is no way to do exactly what you are saying. Instead, try defining CELL_CONTENT_WIDTH like this:
#define CELL_CONTENT_WIDTH (IS_IOS7_AND_UP ? 320.0 : 300.0)
This will do the check at runtime without changing any of your existing code.

Related

How to define Max and Min value of CFIndex?

I try to define a macro like this:
#import <CoreFoundation/CFBase.h>
#if __LLP64__
#define CFIndexMax LONG_LONG_MAX;
#define CFIndexMin LONG_LONG_MIN;
#else
#define CFIndexMax LONG_MAX;
#define CFIndexMin LONG_MIN;
#endif
But Xcode always warn me has no define of __LLP64_ which is conditional defined in CFBase.h.
Your problem is that you are checking the value of __LLP64__ but you want to check for the existence of __LLP64__:
#ifdef __LLP64__
#define CFIndexMax LONG_LONG_MAX
#define CFIndexMin LONG_LONG_MIN
#else
#define CFIndexMax LONG_MAX
#define CFIndexMin LONG_MIN
#endif
However, only Windows uses the LLP64 model. Are you planning to build this code on Windows? If not, you should simplify your code by eliminating the conditional.
Actually, the compiler defines __LLP64__ (or more likely __LP64__).
If you take a look at the CFBase.h pre-processor logic again, you'll see it forcibly defines __LLP64__ when compiling for a 64-bit Windows target:
#if defined(__WIN64__) && !defined(__LLP64__)
#define __LLP64__ 1
#endif
Copyright (c) 1998-20016 Apple Inc.
If you're concerned about the size of CGFloat (or even CFIndex types on macOS, take a look at CGBase.h to see how things are defined:
#if defined(__LP64__) && __LP64__
#define CGFLOAT_TYPE double
#define CGFLOAT_IS_DOUBLE 1
#define CGFLOAT_MIN DBL_MIN
#define CGFLOAT_MAX DBL_MAX
#else
#define CGFLOAT_TYPE float
#define CGFLOAT_IS_DOUBLE 0
#define CGFLOAT_MIN FLT_MIN
#define CGFLOAT_MAX FLT_MAX
#endif
Copyright (c) 2000-2011 Apple Inc.
You can conditionally define your max and min CFIndexes based on the boolean value of CGFLOAT_IS_DOUBLE, which is not changing any time soon.
Lastly, I believe Windows is the only OS whose size of long types are 32 bits in a 64-bit runtime (that is, compared to linux and macOS which are 64 bits in a 64-bit runtime).
If you're sure you're switching on the right define, always check if the variable be defined first in the pre-compiler:
#if defined(__LLP64__) & __LLP64__
// conditionally define more stuff
#endif

Header file not executing if else case

My project contains 3 targets and it requires some credential details specific to target. I have defines.h file where I am checking the current target and then initialising constants.
#ifdef XYZ44DEV
#define COM_CMS_URL #"http://xyz.portal.com"
#define COM_CMS_USER #"test"
#define COM_CMS_PASS #"test"
#elif XYZ44UAT
#define COM_CMS_URL #"http://xyz.uat.portal.com"
#define COM_CMS_USER #"uat"
#define COM_CMS_PASS #"uat"
#else
#define COM_CMS_URL #"http://xyz.prod.portal.com"
#define COM_CMS_USER #"Prod"
#define COM_CMS_PASS #"Prod"
#endif
Any target I run, it goes to else case and takes COM_CMS_USER & COM_CMS_PASS as "Prod". Please let me know, what i am missing here.
You need to add preprocessor Macros in build settings as illustrated in image
the output for
NSLog(#"%#",COM_CMS_USER);
is
2016-05-20 11:58:05.315 CustomKeyboard[2952:687530] test
You have to set preprocessing macro in build setting
image 1 : You have to add macro for each your target
image 2 : For macro , you can set only supported versions

Operator 'defined' requires an identifier ios

I've below code in my project dlog should print the values in console if isConsoleLogActive is YES.
It gives error like Operator 'defined' requires an identifier
#if defined ([Util isConsoleLogActive])// Operator 'defined' requires an identifier in this line
#define DLog(...) NSLog(__VA_ARGS__)
#define DTrace() NSLog(#"%s", __PRETTY_FUNCTION__)
#else
#define DLog(...) /* */
#define DTrace() /* */
#endif
if I use the same code([Util isConsoleLogActive]) in my .m it works perfectly fine. I face this issue only in #define
What could be the issue. Please give me some idea.
The various commands that start with # are preprocessor directives. These get executed before the compilation phase at build time, before your application actually executes. You should use the preprocessor directives to conditionally include different code in your application based on build configuration. The preprocessor, however, is the wrong way to handle conditional execution on a specific platform at runtime; for that, you want your standard "if...else" logic.
If your goal with that statement is to determine if the given selector exists, try respondsToSelector, instead.
Result of
[Util isConsoleLogActive]
is not known at compile-time. So you can not use it with '#if defined'.

#define based upon platform [iPhone or iPad]

I'm trying to make my iPhone app compatible with the iPad.
In a header file I set up some constants.
Because of the larger screen I want some constants used for images to be larger on the iPad than on to the iPhone.
I found some suggestions on the internet to accomplish this:
#if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define imgAmcWidth 656.0f
#define imgAmcHeight 36.0f
#else
#define imgAmcWidth 240.0f
#define imgAmcHeight 20.0f
#endif
This seems to satisfy my needs.
Unfortunately xcode 4 fails to compile this giving an error: 'Token "[" is not valid in preprocessor..' [LLVM GCC 4.2].
What am I doing wrong?
While probably not the most elegant solution but to prevent a major rewrite of the code I decided to use the following trick:
#define iPad UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
#define imgAmcWidth (iPad ? 639.0f : 240.0f)
// etc..
UI_USER_INTERFACE_IDIOM and UIUserInterfaceIdiomPad are not preprocessor things. They are part of iOS, so you should do:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
<define your constants here>
} else {
<define your constants here>
}
See also this if you plan to support iOS versions previous to 3.2

iOS Prefix.pch best practices

I have seen many developers that add various convenience macros to the Prefix.pch of their iOS projects.
What do (or don't) you recommend adding to the iOS Prefix.pch file? What does your Prefix.pch look like?
Ewww… don't put macros in a .pch file! A .pch file is, by definition, a project specific precompiled header. It really shouldn't be used beyond the context of the project and it really shouldn't contain anything but #includes and #imports.
If you have some macros and such that you want to share between headers, then stick 'em in a header file of their own — Common.h or whatever — and #include that at the beginning of the .pch.
For modern iOS and OS X, people should be using Modules. This is enabled by default for new projects, and importing/inclusion is accomplished using #import.
Modules allow the compiler to create an intermediate representation of the contents of a module (e.g. a framework's headers). Much like a PCH, this intermediate representation may be shared across multiple translations. But modules take this one step further because a module is not necessarily target specific, and their declarations need not be localized (to a *.pch). This representation can save you a ton redundant compiler work.
Using modules, you do not need a PCH, and you probably should just do away with them entirely -- in favor of using #import local to the dependency. In that case, a PCH is only saving you from typing inclusions local to dependencies (which IMO you should be doing anyway).
Now, if we look back to the original question: You should avoid filling your PCH with all sorts of random things; Macros, constants, #defines, and all sorts of little libraries. Generally, you should omit what really is unnecessary to the majority of your source files. Putting all sorts of stuff in your PCH is just adding a bunch of weight and dependency. I see people put everything they link and more to in the PCH. In reality, auxiliary frameworks typically only need to be visible to a few translations in most cases. E.g. "Here is our StoreKit stuff - let's import StoreKit only where it must be visible. Specifically, these 3 translations". This keeps your build times down, and helps you keep track of your dependencies, so that you may reuse code more easily. So in an ObjC project, you would usually stop at Foundation. If there is a lot of UI, then you might consider adding UIKit or AppKit to your PCH. This is all assuming you want to optimize build times. One of the problems with large PCHs that include (nearly) everything is that removing unnecessary dependencies is very time consuming. Once your project's dependencies grow and your build times go up, you need to fight back by eliminating unnecessary dependencies in order to reduce your build times. Also, anything that changes often should generally be kept out of your PCH. A change requires a full rebuild. There are some options to share PCHs. If you use PCHs, do aim to support sharing.
As far as what I put in my PCH: I stopped using them for the vast majority of targets years ago. There just usually is not enough in common to qualify. Bear in mind, I write C++, ObjC, ObjC++ and C - the compiler emits one for each lang in your target. So enabling them often resulted in slower compile times and higher I/O. Ultimately, increasing dependency is not a good way to fight dependency in complex projects. Working with multiple languages/dialects, there are is much variation in the dependencies required for a given target. No, I would not advise that as optimal for every project, but that does give some perspective to dependency management in larger projects.
References
http://clang.llvm.org/docs/Modules.html
http://clang.llvm.org/docs/PCHInternals.html
Notes
This question was originally asked a few years before Modules' introduction.
Presently (Xcode 5.0), modules work for C and ObjC, but not C++.
I agree with bbum. My take on the PCH file is that it should contain pretty much only #include or #import statements. So if you have a bunch of helpful, high-level macros, define them in something like Common.h and #import that file, as bbum suggested.
I usually go a step further and use the PCH file to #import a file called XXCategories.h (where XX is the class naming prefix convention you use) that contains #imports for all my UIKit and Foundation class categories: NSString+XXAdditions.h, UIColor+XXAdditons.h, etc.
create an header file "macros.h"
import this header into Prefix.pch
In this macros.h put all the frameworks and other important things.
If you are worried about performance, don't worry, look what apple says:
Headers and Performance
If you are worried that including a master header file may cause your
program to bloat, don’t worry. Because OS X interfaces are implemented
using frameworks, the code for those interfaces resides in a dynamic
shared library and not in your executable. In addition, only the code
used by your program is ever loaded into memory at runtime, so your
in-memory footprint similarly stays small.
As for including a large number of header files during compilation, once again, don’t worry. Xcode provides a precompiled
header facility to speed up compile times. By compiling all the
framework headers at once, there is no need to recompile the headers
unless you add a new framework. In the meantime, you can use any
interface from the included frameworks with little or no performance
penalty.
also in my macros.h I put a lot of constants like:
// delegate
#define UIAppDelegate (AppDelegate *)[[UIApplication sharedApplication] delegate]
#define APPDELEGATE ((AppDelegate *)[[UIApplication sharedApplication] delegate])
// system
#define IS_IPHONE_4INCH (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height==568)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// screen size
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_4 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)
#define IS_RETINA_DISPLAY ([[UIScreen mainScreen] respondsToSelector:#selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))
#define IS_PORTRAIT UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])
#define IS_LANDSCAPE UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])
//system version
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
// math
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
// cores
#define RGB(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define RGBA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:a]
#define MAKECOLOR(R, G, B, A) [UIColor colorWithRed:((float)R/255.0f) green:((float)G/255.0f) blue:((float)B/255.0f) alpha:A]
#define MAKECOLORFROMHEX(hexValue) [UIColor colorWithRed: ((float)((hexValue & 0xFF0000) >> 16))/255.0 green:((float)((hexValue & 0xFF00) >> 8))/255.0 blue:((float)(hexValue & 0xFF))/255.0 alpha:1.0]
//customizations
#define SHOW_STATUS_BAR [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
#define HIDE_STATUS_BAR [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
#define SHOW_NAVIGATION_BAR [self.navigationController setNavigationBarHidden:FALSE];
#define HIDE_NAVIGATION_BAR [self.navigationController setNavigationBarHidden:TRUE];
#define VC_OBJ(x) [[x alloc] init]
#define VC_OBJ_WITH_NIB(x) [[x alloc] initWithNibName : (NSString *)CFSTR(#x) bundle : nil]
#define RESIGN_KEYBOARD [[[UIApplication sharedApplication] keyWindow] endEditing:YES];
#define CLEAR_NOTIFICATION_BADGE [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
#define REGISTER_APPLICATION_FOR_NOTIFICATION_SERVICE [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]
#define HIDE_NETWORK_ACTIVITY_INDICATOR [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
#define SHOW_NETWORK_ACTIVITY_INDICATOR [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

Resources