Enums in pch-file? - ios

I have pch-file with this code:
#import "ServerModel.h"
enum {
SAVE = 1,
REMOVE = 2,
REMOVE_ALL = 3
};
typedef NSInteger RequestType;
and I'm trying to use RequestType in ServerModel.h but compiler doesn't know nothing about my enum. I tried to create header file for my enums and import this file in pch-file but nothing have changed.
So basic problem is: I can't use enums from .pch file in files, that are #imported in this pch-file.
Is there some way to handle this problem? And is pch-file good place to put enums there?
UPD:
I tried to put all this enums in one header file and #import this file in the end of all #imports in pch-file and it doesn't work.
But then I put
#import "Enums.h" // my file with enums
in the beginning of pch-file, before all other #imports and it's working.
I will be glad if somebody will explain the difference in the placement of #import before or after some other #import.
UPD2:
I'll try to make it more clearly:
I have Enums.h with enum:
enum {
SAVE = 1,
REMOVE = 2,
REMOVE_ALL = 3
};
typedef NSInteger RequestType;
MyProject-Prefix.pch with:
#import "ServerModel.h"
#import "Enum.h"
and ServerModel.h with following code:
- (void)unlinkAccountWithRequestType:(RequestType)requestType;
I'm getting an error: Expected a type on this method. I've cleaned my project and getting same error.
When I'm switching #imports like this:
#import "Enums.h"
#import "ServerModel.h"
Everything is good

Case1 : If you import like this
#import "ServerModel.h"
#import "Enums.h"
Then compiler will check ServerModel.h file before Enums.h when it encounters #import "ServerModel.h" statement. And while checking you ServerModel.h it finds a token RequestType and says WTF is RequestType?? and throws error on your face.
Case 2: If you write this
#import "Enums.h"
#import "ServerModel.h"
Then compiler compiles Enums.h successfully and then compiles ServerModel.h and again it finds a token RequestType and says yeah I know this is a typedef of NSInteger which is defined in Enums.h. And finally it moves on happily.

Related

Swift framework - Use Swift class reference in Objective-C class

I am creating Swift framework in which I have to use Objective-C class. So I went through this link. This is the public header of my framework :
#import <UIKit/UIKit.h>
//! Project version number for Test.
FOUNDATION_EXPORT double TestVersionNumber;
//! Project version string for Test.
FOUNDATION_EXPORT const unsigned char TestVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Test/PublicHeader.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
#import <MyTest/MPAppDelegateProxy.h>
Now in class MPAppDelegateProxy, I have to use a Swift class which I have created. This is :
#import "MPAppDelegateProxy.h"
#import "MyTest.h"
#implementation MPAppDelegateProxy
+ (void)proxyAppDelegate {
[MPGlobal MPLog:#"App delegate not set, unable to perform automatic setup." file:#"MPAppDelegateProxy.m" function:#"proxyAppDelegate" line:32];
// rest of code
}
MPGlobal is one of my Swift class. But I am getting :
Use of undeclared identifier 'MPGlobal'
Note : I have added #objC before MPGlobal.
You need to import <Target>-Swift.h file.
This is known as Objective-C Generated Interface Header Name.
You can find it in your Target's build settings.
This file is auto generated by compiler and it needs to be imported in Objective-C files.
change the SWIFT_OBJC_INTERFACE_HEADER_NAME build setting and making it the same across different targets. To do so change the instruction that generates this property from $(SWIFT_MODULE_NAME)-Swift.h to $(PROJECT_NAME)-Swift.h as explained here
After doing this Clean Build Folder by pressing Alt and going into Product menu. Since name of header is shared among targets now it can be imported once in the .m ObjectiveC file and all targets can benefit from Swift classes.
If after building it still shows the error, ensure that the header can be reached from XCode by Cmd clicking on its name. It should open a file that contains code similar to this:
SWIFT_CLASS("_TtC27ProjectName_Summary11MyClass")
#interface MyClass : NSObject
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
#end
If need to ensure that those headers are being generated open a terminal and use this command
find ~/Library/Developer/Xcode/DerivedData -name "*Swift.h"
You should see one header for each target
Another issue that happened to me after those changes is that it started giving errors on ObjectiveC code that I didn't touch. The problem was due to the position of the import, as reported here:
Exactly where at the top of a .m file you #import the hidden bridging
header can make a difference. The usual sign of trouble is that you
get an “Unknown type name” compile error, where the unknown type is a
class declared in Objective-C. The solution is to #import the .h file
containing the declaration for the unknown type in your Objective-C
files as well, before you #import the hidden bridging header. Having
to do this can be an annoyance, especially if the Objective-C file in
question has no need to know about this class, but it resolves the
issue and allows compilation to proceed.
At the very end the code compiles and runs on device and simulator!
Original answer
Also you can try this,
You needed to import the -Swift.h for for both the framework and the app target
For Example :
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <Foundation/Foundation.h>
#import "XLPagerTabStrip-Swift.h"
#import "RealmSwift-Swift.h"
...... // Add all frameworks, subclasses, and dependance ios frameworks
#import "MyProject-Swift.h"
You can read this article How to import file header and check paths

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.

Objective-C: Expected a type error

I am trying to follow a tutorial for using a stylesheet from Nick Kuh's book "iPhone App Development". The stylesheet header file is throwing:
"Expected a type"
errors which I think normally reflects a circular problem. However, in this case the only import is to Foundation.h. (The implementation file, btw, does not throw any errors and seems to be fine.) Here is the header file in its entirety.
#import <Foundation/Foundation.h>
typedef enum : int {
IDLabelTypeName = 0,
IDLabelTypeBirthdayDate,
IDLabelTypeDaysUntilBirthday,
IDLabelTypeDaysUntilBirthdaySubText,
IDLabelTypeLarge
}
IDLabelType;
#interface IDStyleSheet : NSObject
+(void)initStyles;
+(void)styleLabel:(UILabel *)label withType:(IDLabelType)labelType;//throws red error
+(void)styleTextView:(UITextView *)textView;//throws red error
+(void)styleRoundCorneredView:(UIView *)view;//throws red error
#end
Can anyone see why these errors are occurring?
UILabel, UITextView ... are defined in the UIKit framework, therefore you have to
#import <UIKit/UIKit.h>
(which then implicitly imports Foundation). You can also use the
more modern "module" syntax:
#import UIKit;

typedef in header file not getting picked up by xcode

I have a typedef in A.h file, and I import that A.h file in B.h that makes use of the same typedef.
For the longest time everything worked fine, but now it breaks complaining that it doesn't recognize the typedef and gives "Expect type" error in xcode, even tho xcode highlights the typedef in the second file, meaning that it knows they are defined else where.
if I manually redefine that typedef then the error goes away. but I get a warning that I am redefining a typedef and that it is a C11 feature.
I tried deleting the derived data, but the error stays. It looks like xcode is trying to look up the typedef before inserting the import files. Any clue? I'm using xcode 4.6
//WebService.h
#import <Foundation/Foundation.h>
#import "AppDelegate.h"
#interface WebService : NSObject
typedef void(^loginUserWithUserNameandPaswordCompletion)(NSDictionary *, NSError*);
+(void)createUserWithName:(NSString*)name
andEmail:(NSString*)email
andPassword:(NSString*)password
onCompletion:(loginUserWithUserNameandPaswordCompletion) complete;
#end
//DataCenter.h
#import <Foundation/Foundation.h>
#import "WebService.h"
#import "AppDelegate.h"
typedef void(^loginUserWithUserNameandPaswordCompletion)(NSDictionary *, NSError*);
#interface DataCenter : NSObject
+(void) logInUserWithEmail:(NSString*) email
andPassword:(NSString*)password
onCompletion:(loginUserWithUserNameandPaswordCompletion)complete;
#end
Try putting typedef before your #interface in WebService.h.
used #class as mentioned by gberginc

Unknown type name when trying to include a library

I'm trying to use Novocaine in an iPhone application I'm building. I can't figure out how to get around this error I'm getting:
Unknown type name 'RingBuffer'
Here's my file structure:
...with those files under Novocaine being the ones pulled from the Github repo for Novocaine. Here's my header file for DDViewController.
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "UICoordButton.h"
#import "Novocaine.h"
#import "RingBuffer.h"
#import "AudioFileReader.h"
#import "AudioFileWriter.h"
#interface DDViewController : UIViewController
{
RingBuffer *ringBuffer;
Novocaine *audioManager;
AudioFileReader *fileReader;
AudioFileWriter *fileWriter;
}
- (IBAction)changeColor:(id)sender;
- (IBAction)changeColor2:(id)sender;
#end
I've tried a solution that I found on another question, which suggests that this should work:
#class RingBuffer;
#interface DDViewController : UIViewController
{
...
But that just gives me Redefinition of 'RingBuffer' as a different kind of symbol.
How can I fix this problem and use RingBuffer?
RingBuffer is a C++ class. I recommend you change the extension of your Objective-C files from .m to .mm which will make them Objective-C++
Found the answer (or I guess a combination of answers):
Follow coryalder's advice for setting the compiler default to Objective-C++ as described here.
Also, change all .m files to .mm files, and finally add -fno-objc-arc compiler flags to all the .mm files -- which is described in detail here.

Resources