XCode Header Search Paths for global struct - objective-c

I created a struct called PointInt that is simply two integers (like CGPoint but with ints) and I want it to be a global struct just like CGPoint. I also created a category for NSValue for this.
I've looked all over the Internet and it seems that Build Settings -> Header Search Paths is the way to go. However, I have no idea what values to put into it. I've tried $(PROJECT_DIR)/PointInt/** and a bunch of similar strings but the compiler does not recognize it. How do I #import a .h file for the struct, then another .h and a .m for the category? And is there anything else that has to be done?

Add the header file with the struct to your prefix header. One will have been automatically created for you when you created the project called [project]-Prefix.pch in the "Supporting Files" directory.
Add it in between #ifdef __OBJC__ and #endif.
It will then be available throughout your project.

Related

Using Obj-C class extension in Swift?

I added some Obj-C code (the excellent Expressions) to my Swift project using Xcode's Add files... but it did not ask me if I wanted to make a bridging header. So I made one myself in the Obj-C code's group, edited it to #import the single header I needed, and made sure that file was referenced in the Swift Compiler in Build Settings. I then looked through the Obj-C code and made sure the .m files were in the target - they were, and they're listed in Compile Sources.
The header in question contains this:
#interface NSNumber (Expression)
+ (NSNumber *)numberByParsingExpression:(NSString *)expression;
+ (NSNumber *)numberByParsingExpression:(NSString *)expression withVariables:(NSDictionary *)varDictionary;
#end
Now I am trying to call this code using the same basic syntax as this post:
let result = NSNumber.numberByParsingExpression(f.1)
along with several variations on the theme. But it won't compile, "Type 'NSNumber' has no member 'numberByParsingExpression'".
Did I miss a step here?
According to https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
You can create a bridging header yourself by choosing File > New >
File > (iOS, watchOS, tvOS, or OS X) > Source > Header File.
You’ll need to edit the bridging header file to expose your
Objective-C code to your Swift code.
In your Objective-C bridging header file, import every Objective-C
header you want to expose to Swift. For example:
In Build Settings, in Swift Compiler - Code Generation, make sure the
Objective-C Bridging Header build setting under has a path to the
bridging header file. The path should be relative to your project,
similar to the way your Info.plist path is specified in Build
Settings. In most cases, you should not need to modify this setting.
Any public Objective-C headers listed in this bridging header file
will be visible to Swift. The Objective-C functionality will be
available in any Swift file within that target automatically, without
any import statements. Use your custom Objective-C code with the same
Swift syntax you use with system classes.
If you already did this correctly, and it still isn't working, try deleting the projects derived data, and clean building your project.
Ok, this turns out to be an Xcode peccadillo.
When you create the header file within the group, it actually places it physically in the source folder. So in my case the header was created in /project/subproject/.h although it appeared within Xcode to be part of the base folder, /project/.h.
So in fact there were two headers, one in the right place with nothing in it, and another in the wrong place that was the one that was being edited within Xcode. So you have to look at the file inspector to make sure it placed the bridging header in the right place!

I need to create separate file for all the constants of my project

In my project I have a requirement to create separate file for all constants that i am using in separate classes in the same project.
I seen some examples but they are saying about creating in '.h' file and again they are implementing them in '.m' files. But i need only '.h'file to create all constants and i have to use all those constants by importing that '.h' file in every class of my project.
ADD a new file.
Right click on the file inspector
choose New File
The pop up window select ios>C and C++>HeaderFile[Figure]
Give name Constants
Add #define OK #"OK"
Go to View Controller include file in header #import "Constants.h"
OR Define in pch file ,so that all View controllers can access the file
In viewDidLoad NSLog(#"%#",OK);
You can create .h file and use #define to create constants and then include your file to prefix file of your project. Though I prefer to use extern constants which you declare in .h file and define in .m file. This help to track possible warnings in your code at compilation time.
You've pretty much answered your own question, to the point where I'm not sure exactly what you're asking - you can just create a header file (.h) with your constants, and import it into your other classes. You don't need to create a corresponding implementation (.m) file. If you're using your constants throughout your code you could import them in your prefix header and have them automatically available.

Adding pre compiled headers in Xcode 4 Objective-C

This question is related to this:
Constants in Objective-C
I would like to add pre compiled headers to my project to store app constants. I want to this as an alternative to having a constants.h file and importing it wherever it's needed. Is my thinking correct here?
On the above thread a guy mentioned modifying "YourAppNameHere-Prefix.pch".. I'm not sure this is a good approach.
How exactly can I create my own *.pch file and add it to my Xcode project so I can store application level constants?
I have tried googling/searching here for this but I'm just getting Objective-C++ and Clang stuff.. I'm not sure this is relevant.
Cheers,
Conor
My answer probably not just in time, and especially for Xcode 6 but i hope i'll help other, who already want's to create it's own constant.h file and set it on all of project objects.
So
Create constant.h file by NSObject.
Put all of constants you need in .h file before #interface:
#import <...>
#define kSomeFirstConstant 1 //where 1 is an integer value
#define kSomeSecondConstant 2 //where 2 is an integer value
#interface Constant: NSObject
Create precompiled header file .pch (eg: precompiledFile.pch)
Put #import "constant.h" in .pch file right between #define and #endif:
#define ..._pch
#import "constant.h"
#endif
Configure prefix name and some other options in Project navigator, Building Settings of your project target:
Apple LLVM 6.0 Language
Increase sharing of Precompiled headers - NO
Precompile prefix header - YES
Prefix Header - TargetName/precompiledFile.pch (eg: MyTarget/precompiledFile.pch)
After that, run building process and all of your constant in constant.h file will be accessible in all of your project objects.
Also read this: http://qualitycoding.org/precompiled-headers/

Duplicate symbol at link time

Just as background, there are no compile-time errors or warnings in the subject project "Project".
There are numerous occurrences of using the same instance variable name in two (or more classes). In the following, I'll use the variable name "index" as an example. It appears as an instance variable in class1 and class2. The variable has different but similar meanings in both classes, hence the use of the common term.
I define index in the header file for both class1 and class2, for example:
#interface class1 : NSObject
{
int index;
}
...
Repeat for class2.
When I build the project, Xcode reports:
Duplicate symbol _index in /Project/build/Project.build/Debug-iphonesimulator/Project.build/Objects-normal/i386/class1.o and /Project/build/Project.build/Debug-iphonesimulator/Project.build/Objects-normal/i386/class2.o
Changing the occurrences of "index" to "indexnotverycommon", reports the same error with the new name.
Changing the occurrences to "index1" and "index2" respectively gets rid of the error. Xcode then reports the next duplicate it finds during linking, and so on, and so on.
I can continue the renaming process although I'd rather not, as I'm concerned that there is a more pathological underlying issue.
Any advice or question is appreciated.
index is a also a C function and thus a very unfortunate name in Objective-C.
This article describes why it's not a good idea to use index as a name.
I'm not sure why you get duplicate symbols though.
I figured it out using the Xcode find-in-project feature. Thanks for the advice about index.
don't #include or #import .m files. Just add those .m files into the Target | Build Phases. Don't add .h files into build phases, but #import .h files wherever you need those functions.
The compiler knows that it's just a header file "for information only" and that the bodies of the functions will be available when it will compile the .m files and put them all into 1 executable
The header file contains only forward declarations. Compiler knows that the body is either defined in another file or is in a lib linked to the project
The tip to check for an #import "Xxx.m" instead of the correct .h worked.
A quick workspace wide search for "Xxx.m" spotted the error in the include which was causing the link error.

Forward-declare enum in Objective-C

I'm having trouble with enum visibility in an Objective-C program. I have two header files, and one defines a typedef enum. Another file needs to use the typedef'd type.
In straight C, I would simply #include the other header file, but in Objective-C, it's recommended not to use #import between header files, instead using forward #class declarations as needed. However, I can't figure out how to forward-declare an enumeration type.
I don't need the actual enumerated values, except in the corresponding .m implementation file, where I can safely #import away. So how can I get the typedef enum to be recognized in the header?
Most recent way (Swift 3; May 2017) to forward declare the enum (NS_ENUM/NS_OPTION) in objective-c is to use the following:
// Forward declaration for XYZCharacterType in other header say XYZCharacter.h
typedef NS_ENUM(NSUInteger, XYZCharacterType);
// Enum declaration header: "XYZEnumType.h"
#ifndef XYZCharacterType_h
#define XYZCharacterType_h
typedef NS_ENUM(NSUInteger, XYZEnumType) {
XYZCharacterTypeNotSet,
XYZCharacterTypeAgent,
XYZCharacterTypeKiller,
};
#endif /* XYZCharacterType_h */`
The answer to your question is to either go ahead and import the typedef header file or to use a generic type like NSInteger instead of the enum type.
However, there is more reason to not importing a header file than just compile speed.
Not importing a header file also reduces your inadvertent access to extraneous classes.
For example, say you have a TrackFileChanges class that tracks the file system for changes to a specific file, and you have a CachedFile class that stores cached data from a file. The latter might use a private ivar of type TrackFileChanges*, but for uses of CachedFile, this is simply an implementation detail (ideally, the ivar would be auto-generated with a private property using the new runtime, but thats not possible if you're using the old run time).
So clients that #import "CachedFile.h" probably do not need or want access to TrackFileChanges.h. And if they do, they should make it clear by #importing it themselves. By using #class TrackFileChanges instea of #import "TrackFileChanges.h" in CachedFile.h you improve the encapsulation.
But all that said, there is nothing awrong with importing a header file from a second header file if the second header wants to expose the first to all clients. For example, header files that declare classes need to be imported directly in subclassing header files, and header files declaring protocols might well be imported directly (although youy can use #protocol ABC; to avoid this).
Go ahead and use #import. The only reason people recommend to use #class when possible is because it makes your code slightly faster to compile. However, there is no issue with #importing one .h file from another. In fact, you need to do this when extending another class.
If you are ok using compiler extensions, you could use this order in Clang:
enum Enum;
typedef enum Enum Enum2;
void f(Enum2); // ok. it sees this type's true name.
enum Enum {
E_1
};
// ok. now its declaration is visible and we can use it.
void f(Enum2 e) {
}
Note: It will trigger a -Wpedantic warning.
If you are using C++11, you should use their enums, which are safe to forward declare -- e.g. enum class Enum:uint8_t; (not a compiler extension).
What worked for a forward declaration of an enum for me in an Objective C .h file was look in the ProjectName-Swift.h file and see what it put, which happened to be the following:
enum SwiftEnumName : NSInteger;
I needed this forward declaration because I had a function parameter type of SwiftEnumName. And it wouldn't let me put the ProjectName-Swift.h import in the Objective C .h file.
Then in the Objective C .m file I just had the #import "ProjectName-Swift.h" in it and just used the SwiftEnum normally.
This was using Swift 4.1.2.
You'd have to either #import them anyway or create a separate header file containing only the typedef. Not importing header files in a header makes the compilation faster, but doesn't change anything else.
Why doesn't C++ support forward declaration of enums?