How can I declare a config.h file, add it to my App-Prefix.pch, and then use it globally in my app? - ios

I want to create a Config.h file to house all my static const strings that should be global to my application.
I've created a new Config.h file, but there are a few things I'm unaware of.
1) How do I declare variables. A or B?
A)
#define hotelURLString4 = #"http://blah.herokuapp.com/api/v1/hotels/";
B)
static NSString * const hotelURLString2 = #"http://blah.herokuapp.com/api/v1/hotels/";
2) I can't seem to use this file. If I try to import the Config.h directly into a file of mine, I get a "Config.h file not found" error in xcode. If I include it in my AppName-Prefix.pch up at the top via...
#import <Availability.h>
#import "Config.h"
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
That does not seem to work either. How do I do this.
3) How do I access the variable declared/defined. Do I call Config.hotelURLString, or [Config hotelURLString]... or how do I access it?
===================================================================
============================ UPDATE ===============================
1) I created my header like this... am I not doing something correctly, because I tried again and it won't work either.
2) This is my AppName-Prefix.pch file.
#import <Availability.h>
#import "Config.h"
#import "MyHeader.h"
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
3) Here is my Project Navigator

To answer question 1, method B is probably better, although you should name your variable more like:
kHoteUrlString2
And preferably something more descriptive then just the numbers, but the main point here is the lower case k and the uppercase first letter. This is a C/ObjC naming convention for constants.
As for question 2, it sounds like your file isn't actually in the project. Some more details are needed to answer this part of the question, and I'll update my answer if the question has more details added.
As for question 3, you use the variable exactly as you would as if you had declared it at the top of whatever file you're using. Objective-C doesn't have namespaces.

Related

Xcode 8 (Swift): core.hpp header must be compiled as C++

I am using the OpenCV iOS Framework in a project. I followed the necessary steps to include the framework into the project.
The Project is written using Swift 3.
One of my classes that contains the core functionality of the App is written in Objective-C++. I included the header of the class in my Bridge-header file but when trying to run the project I get the following error:
error core.hpp header must be compiled as C++
After researching online and on SO, the most common solution presented was to create a Wrapper class that would be imported in the bridge header. However, after following this article I face the same problem.
The Header file of my class looks like this:
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#define IMAGE_CLASS UIImage
#elif TARGET_OS_MAC
#import <Cocoa/Cocoa.h>
#define IMAGE_CLASS NSImage
#endif
#import <AGGeometryKit/AGKQuad.h>
#import <stdio.h>
#import <opencv2/opencv.hpp>
#import <Foundation/Foundation.h>
typedef void (^DebugBlock)(cv::Mat current_image, std::string current_image_name);
#interface ImageScanner : NSObject
/**
* Singleton for access to the scanner.
*
* #return Shared scanner.
*/
+ (instancetype)sharedScanner;
Does anyone have an idea what I might be missing?
Thank you in advance!
G.
had the same problem.. solved by importing any file that use openCV in the wrapperClass.mm file ...
SO Answer here

Calling Obj-C method from C

I've got a library written in C, where I need to push a call to a method written in Obj-c.
I don't want to modify the original code too much, so I decided to create a "bridge" class to handle the calls between C and ObjC:
DRMBridge.h
#ifndef DRMBridge_h
#define DRMBridge_h
#include "DRMBridgeObjC.h"
void bridge_test();
#endif
DRMBridge.c
#import "DRMBridge.h"
void bridge_test() {
ctest();
}
Above is compiled as C
Now here's my objc code:
DRMBridgeObjC.h
#ifndef DRMBridgeObjC_h
#define DRMBridgeObjC_h
#import <Foundation/Foundation.h>
#interface DRMBridgeObjC : NSObject
+(void) test;
#end
void ctest();
#endif
DRMBridgeObjC.m
#import "DRMBridgeObjC.h"
#implementation DRMBridgeObjC : NSObject
+(void) test {
NSLog(#"OH YEAH!");
}
#end
void ctest() {
[DRMBridgeObjC test];
}
Quite simple.
In the C library I want to call my code from I've added:
#include "DRMBridge.h"
into the .h file and
bridge_test();
in .c file.
Now the best part, when I compile I get:
In file included from /Users/krystian/projects/mdb-reader-lib/reader-Include/ios/MDBReader/Class/DRM/DRMBridge.c:5:
In file included from /Users/krystian/projects/mdb-reader-lib/reader-Include/ios/MDBReader/Class/DRM/DRMBridge.h:8:
In file included from /Users/krystian/projects/mdb-reader-lib/reader-Include/ios/MDBReader/Class/DRM/DRMBridgeObjC.h:12:
In file included from /Applications/Xcode64.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:8:
/Applications/Xcode64.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:400:1: error: expected identifier or '('
#class NSString, Protocol;
^
[...]
I went looking, and found this: ios - Parse Issues in NSObjCRuntime, NSZone, and NSObject
However my pch file looks like this:
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
I think the issue I have is that the C compiler tries to compile my ObjC file first, instead of the other way around.
I've tried changing the order of files inside Compile Sources to make sure that my .m file is above .c file, but still no go.
Something else I have found which made me lost:
when I follow this answer: https://stackoverflow.com/a/20461780/487605 and change the library itself to .m, and call [DRMBridgeObjC test] code from there - it works.... Compiles fine, no errors given, works fine.
This implies to me, that there's something screwed up with my DRMBridge, but what?
Thanks
Krystian
You've seen the solution already. Use #ifdef __ OBJC__ in your Objective-C header file so that only the plain C bits are compiled when including the file from C
DRMBridge.h
#ifndef DRMBridge_h
#define DRMBridge_h
#include <CoreFoundation/CoreFoundation.h> //or put in .pch
CF_EXPORT void bridge_test();
#endif
DRMBridge.m
#import "DRMBridge.h"
#import "DRMBridgeObjC.h"
void bridge_test() {
ctest(); //or [DRMBridgeObjC test]; if you like
}
Thats all. And you can include DRMBridge.h in whatever you like: in .c, in .m, in .cpp.

Preventing duplicate entry messages

I have two classes that are pretty much identical but one is made for OS X and the other one is made for iOS. Then I have a header file like this:
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
#import "ClassForOSX.h"
#else
#import "ClassForIOS.h"
#endif
The problem is because both classes are included in the project, xcode compiles both and I have a lot of duplicate entries on the errors, because methods have the same name on both classes.
Is there a way to prevent a class from compiling, even if it is included on the project, unless the class is meant for the target?
Yes I know I can include/exclude classes from targets but I am dealing with hundreds of classes in both sides and multiple targets and that would generate a lot of include/exclude operations that will eventually go wrong. I was wondering if there is some solution in code that can just allow a class to compile if the target is right.
Use targets is best for your case. But You can do it in code
note add or remove __MAC_OS_X_VERSION_MIN_REQUIRED at Preprocessor Macros at target->Build Settings
ClassForIOS.h file
#ifndef __MAC_OS_X_VERSION_MIN_REQUIRED
#import <Foundation/Foundation.h>
#interface ClassForIOS : NSObject
// interface
#end
#endif
ClassForIOS.m file
#ifndef __MAC_OS_X_VERSION_MIN_REQUIRED
#import "ClassForIOS.h"
#implementation ClassForIOS
// implementation code
#end
#endif
ClassForOSX.h file
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
#import <Foundation/Foundation.h>
#interface ClassForOSX : NSObject
// interface
#end
#endif
ClassForOSX.m file
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
#import "ClassForOSX.h"
#implementation ClassForOSX
// implementation code
#end
#endif

What can be the cause of "use of undeclared identifier LOG_LEVEL_VERBOSE" message

I'm trying to configure cocoalumberjack and when I've added ddLogLevel set to LOG_LEVEL_VERBOSE XCode throws "use of undeclared identifier" error. Why is that? How to avoid?
This question indicates that clearing DerivedData and restarting Xcode solves this kind of error.
However you should not include variables in the pre-compiled header as it will be included in every source file and prefix files are somewhat complicated compared to normal header files.
Better is to have use a Constants.h file which contains:
extern int ddLogLevel;
and #import that into your prefix file.
Then create an Constants.m with:
int ddLogLevel =
#ifdef DEBUG
LOG_LEVEL_VERBOSE;
#else
LOG_LEVEL_ERROR;
#endif
This way there is only one instance of ddLogLevel and it can be easily changed at runtime if necessary.
See this question for hints about prefix file best practices.
What solved it for me was changing #import <CocoaLumberjack/CocoaLumberjack.h> to #import CocoaLumberjack;, when using Xcode 8.0 for an Objective-C project.
Droppy’s post is correct and I recommend doing that, but I would like to address the question directly. There is a flaw in your code that may be resulting in the error.
LOG_LEVEL_VERBOSE is defined in DDLog.h. Your header file only imports DDLog.h if __OBJC__ is defined, but uses LOG_LEVEL_VERBOSE without this condition. Therefore if __OBJC__ is not defined, LOG_LEVEL_VERBOSE will be undefined.
Why would __OBJC__ not be defined? The prefix header is prepended to C, C++, Objective-C and Objective-C++ files. Since __OBJC__ is only defined for the latter two, if there are any C or C++ files in your project then the error will occur.
Knowing this, it is clear the ddLogLevel definition should be inside the #ifdef __OBJC__ check. However, you should do what Droppy said, and also make sure all Objective-C imports go inside the check.
For people who use "CocoaLumberjack 2.X" and still facing same issue after pod update, please try to import "DDLegacyMacros.h".
For prefix file users, try something like this :
#ifdef __OBJC__
...
...
#import <DDTTYLogger.h>
#import <DDLog.h>
#import <DDLegacyMacros.h>
#endif
Hope this helps someone else.

OpenCV compiler error when using Stitcher under iOS

Whenever I try to use the OpenCV Stitcher class in iOS and I include the stitcher-header ( #include ) I end up with a compile error "Expected '{'" in exposure_compensate.hpp. Apparently the line
enum { NO, GAIN, GAIN_BLOCKS };
is causing some sort of error.
I am very new to openCV but using other functions like filter2d() work as expected. How can I resolve this?
Try
#import <opencv2/opencv.hpp>
then
#import <UIKit/UIKit.h>
Update: this answer only highlights the bare minimum fix of the problem, and perhaps the root cause: order of dependencies. Please refer to other answers for better code / setup that you put in your project.
In your project, create a Prefix Header, MyProject.pch, and set it in your project's build settings.
Then within that pch file, do something like this:
#ifdef __cplusplus
# include <opencv2/opencv.hpp>
# include <opencv2/stitching/detail/blenders.hpp>
# include <opencv2/stitching/detail/exposure_compensate.hpp>
#else
# import <Foundation/Foundation.h>
# import <UIKit/UIKit.h>
# import <Availability.h>
#endif
I also ran into this problem. As G. Führ ensure you include the opencv headers first. The easiest way to do this is add:
#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#endif
near the top of the apps "Appname-Prefix.pch" header. This is a precompiled header and makes it easy to guarantee that your opencv header will be included before any of the apple headers.
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
This means you won't accidentally include an apple header before this anywhere else in the app.
I had a similar issue and I solved editing directly the opencv-framework files involved (in your case compensate.hpp) and comment from them the definition of the NO enum case definition. In this case the file was blender.hpp, but compensate.hpp has the same structure
Hope this helps
I solved this issue by importing any Apple headers before those of OpenCV, as mentioned in the beginning of the header:
#if defined(NO)
# warning Detected Apple 'NO' macro definition, it can cause build conflicts. Please, include this header before any Apple headers.
#endif
Hope that helps.
In my case, I create a vertical image stitching app with openCV, error show as screenshot below. It is from exposure_compensate.hpp and blenders.hpp. From the error description, the top file is ../CVWrapper.mm, which is in my project instead of openCV pod project.
As above guys said, there is some conflict issue between C++ and Apple MACRO. And we should put C++ header above Apple header.
First, I try a workaround from internet, which said "replace NO with NO_EXPOSURE_COMPENSATOR = 0". This worked, but it modified openCV source code, I don't want to do that because I will not do version control on Pod files, then if other guys clone my repo/project, they will need to do the same modification on those source code.
Then, I follow the error message in Xcode, I did following changes in my CVWrapper.mm file. After that, those two error disappear.
// Before change
#import "CVWrapper.h"
#import "UIImage+OpenCV.h"
#import "stitching.h"
#import "UIImage+Rotate.h"
// After change
#import "stitching.h"
#import "CVWrapper.h"
#import "UIImage+OpenCV.h"
#import "UIImage+Rotate.h"

Resources