How can define a "header import expression" as a Macro in Objective-C? - objective-c

How can I define a Objective-C macro like: #define IMPORT(ClsName), so that IMPORT(AManager) expands to: #import "AManager.h"?

Related

Project-Swift.h in Project-Prefix.pch casuse no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed warning

I have a project that is written in Objective-C and I am trying to add Swift to it. I have read several places that I can import my Project-Swift.h header in my Project-Prefix.pch. This works but I get a bunch of no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed warnings.
Am I doing something wrong or is it not possible to import the Project-Swift.h header in Project-Prefix.pch?
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Project-Swift.h"
#endif

updated advice on setting constants in Objective-C?

I read through the advice here Constants in Objective-C, but I find two errors in the accepted answer:
I keep getting linker errors when I implement the approach of using .m and .h
In my constants.m file, I get the error "unknown type" for NSString
I am also getting an error following the advice from #VictorHanHee
as a further suggestion of how to link the constants to a .pch file:
I don't have a .pch file by default, and when I create a new one it
doesn't have the formatting expected from the answer.
All I have done is create constants.h and constants.m and put the constant declarations in them as provided in the accepted answer. I also created a .pch file, but as I said it doesn't at all match VictorHanHee's description.
Is this older posting outdated, or if not what am I missing? I don't really know how to go forward with a linker error. I simply want to have a file constants.h where I declare all constants and can include this file in as many classes as I want to make life easier. Can someone tell me how to do this nowadays or point to a more recent discussion?
Also here is the linker error (or part of log I can copy and paste anyway, not full message)
-[AccountInfoViewController viewDidLoad] in AccountInfoViewController.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As you can see, I am trying to access the constant from viewDidLoad. I am simply trying to print it out with NSLog.
Here are the .h and .m files I was originally using:
.h
extern NSString * const PREFS_MY_CONSTANT;
.m
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
Ok here is the template that actually seems to work:
.h
#ifndef Project_prefs_h
#define Project_prefs_h
#endif
extern NSString * const PREFS_MY_CONSTANT;
.m
#import <Foundation/Foundation.h>
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
So the older post is perhaps misleading or I misunderstood them when they said remove everything apart from the constants - but if you don't actually want to remove everything, shouldn't you say so? That's a fair amount of text in there not to mention...
In recent version of Xcode there is no ProjectName-Prefix.pch created automatically file so you should import the file where it is required then try using the constant.
Easiest way:
// Prefs.h
#import <Foundation/Foundation.h>
#define PREFS_MY_CONSTANT #"prefs_my_constant"
Better way:
// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;
// Prefs.m
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
There are a few different ways to create constants in Objective-C, but the easiest way is to use #define statements.
To start, create a new header file. This is where we’ll store all the constants. Name it something original like “Constants.h”.
Here’s a sample file with a few constants:
//
// Constants.h
// App Name
#import <Foundation/Foundation.h>
#define NUM_SECTIONS 7
#define NUM_SECTION_1_ITEMS 2
#define NUM_SECTION_2_ITEMS 14
#define NUM_SECTION_3_ITEMS 5
#define APP_TITLE #"App Name"
#define APP_AUTHOR #"Miscellanea"
To use these constants in your project, you need to import your header file in each implementation file (*.m) where you’ll be referencing them.
#import "Constants.h"
– (void)viewDidLoad
{
self.title = APP_TITLE;
for (int i = 0; i < NUM_SECTIONS; ++ i)
{
// etc.
}
}
Here is the template that does seem to work. It's not different from the old answer except that you don't delete everything apart from the constants.
.h
#ifndef Project_prefs_h
#define Project_prefs_h
#endif
extern NSString * const PREFS_MY_CONSTANT;
.m
#import <Foundation/Foundation.h>
NSString * const PREFS_MY_CONSTANT = #"prefs_my_constant";
Apart from this it appears no longer possible to use .pch file to automatically include the constants across all classes.

C preprocessor directive to conditionally compile method calls with square brackets

I know I can use preprocessor macros to conditionally compile certain method calls, for example:
#if SOMETHING
#define fmod(...)
#endif
...
fmod(34.0, 452.0); //this line doesn't get compiled if SOMETHING != 0.
Can I use the same procedure to conditionally compile method calls with opening and closing brackets?
Say I'd like to conditionally compile all calls to the class MyClass:
[MyClass doSomething];
[MyClass doSomethingElse];
#define MyClass[...] produces:
[ doSomething];
And that's an error. Any thoughts?
This is a workaround rely on fact that calling method on nil is no operation
#interface MyClassImpl : NSObject
+ (void)doSomething;
#end
#if SOMETHING
#define MyClass MyClassImpl
#else
#define MyClass ((Class)Nil)
#endif
You won't have any luck overloading the square brackets with macros, but you can flesh out your macro to have the effect you want with different syntax. Conditionally define a macro that takes an argument. In one case, the macro will resolve to just the argument, in the other case, the macro will resolve to white space.
(Edited to use variadic macro)
#define COMPILE_CONDITIONAL
#if defined(COMPILE_CONDITIONAL)
#define conditional(...) __VA_ARGS__
#else
#define conditional(...)
#endif
Then your use cases would look like:
conditional(fmod(34.0, 452.0));
conditional(MyClass doSomething);
conditional(MyClass doSomethingElse);
You will probably end up using a shorter macro than "conditional" typing that on every line gets old fast.

How to silence 'Expected a type' Xcode compiler warnings? [duplicate]

This question already has answers here:
Forward-declare enum in Objective-C
(6 answers)
Closed 8 years ago.
Is there any way to silence Xcode compiler warnings because of unknown types like with #class?
I defined a type in a single .h file that can be reused throughout the app:
#ifndef Apsiape_InterfaceDefinitions_h
#define Apsiape_InterfaceDefinitions_h
#define COLOR_ALERT_RED [UIColor colorWithRed:1 green:0.3 blue:0.3 alpha:1]
...
typedef enum {
BYEdgeTypeNone = 0,
BYEdgeTypeTop,
BYEdgeTypeLeft,
BYEdgeTypeBottom,
BYEdgeTypeRight
} BYEdgeType;
#endif
And one of my classes uses the BYEdgeType type for a custom protocol in the .h file:
#import <UIKit/UIKit.h>
#protocol BYPullScrollViewDelegate <NSObject>
- (void)pullScrollView:(UIScrollView*)pullScrollView didScrollToPage:(NSInteger)page;
- (void)pullScrollView:(UIScrollView*)pullScrollView didDetectPullingAtEdge:(BYEdgeType)edge;
#end
I want my InterfaceDefinitions.h file to be in the .m file of my class, but if I don't import it in the .m of the class Xcode (of course) complains that it "Expected a type" (BYEdgeType). How can I silence this warning #class-style?
Thanks in advance
Is the protocol defined in a header (.h) file? If so, to use enums and #defines in the .h file, you'll have to import the header with those definitions in that .h file.

How to make NSString macro?

How to make a macro that represents a constant NSString value? I'm getting
"Multi-character character constant" and "Character constant too long for its type" warnings when defining in Xcode 4:
#define LEVELTYPEGLASS #"Glass"
Do I need to escape something?
Avoid using defines for string constants. Define as an extern in the header file like this:
extern NSString * const MYLevelTypeGlass;
And them implement in any implementation file:
NSString * const MYLevelTypeGlass = #"Glass";
This gives a few more characters to type, but adds allot of benefits like better typing for Xcode, guaranteed object identity (no duplicate strings). This is how Apple do it, if its good enough for them, it should be good for you.
The solution suggested by PeyloW is great. But I just want to note that I got the solution working after I have added #import "Foundation/Foundation.h" to header file. So the header file Constants.h should look like:
#import "Foundation/Foundation.h"
extern NSString * const LEVELTYPEGLASS;
#define IMAGECOUNT 5
...
Then, implementation file looks like:
#import "Constants.h"
NSString * const LEVELTYPEGLASS = #"Glass";
And if you need to include that into whole project you need to import that in -Prefix.pch file:
#import "Constants.h"
In that case, all the macro definitions resides in Constants.h header file, and some NSString constants resides in Constants.m implementation file. Again, thanks to PeyloW :)