Xcode picks wrong version of header file with same name - ios

A similar question has been asked and answered here, however the solution provided does not solve my problem.
My Project has two targets: A Cocoa Framework (macOS) and a Cocoa Touch Framework (iOS).
The Frameworks share a lot of source files and headers, but there are files that are specific to each framework (due to platform differences).
In particular, both frameworks each have a class named ViewController.
On iOS, it is declared like this:
($(SRC_ROOT)/Platforms/iOS/ViewController/ViewController.h:)
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
...
On the Mac, like this:
($(SRC_ROOT)/Platforms/macOS/ViewController/ViewController.h:)
#import <Cocoa/Cocoa.h>
#interface ViewController : NSViewController
...
I also have a third class, Manager, that is common to both platforms.
It is just a subclass of NSObject and thus its header file only needs to import the platform-agnostic <Foundation/Foundation.h>.
But this class's methods interact with the aforementioned ViewController, so the implementation file imports that header:
($(SRC_ROOT)/Common/Manager.m:)
#import "Manager.h"
#import "ViewController.h" // <-- THIS
#implementation Manager
...
Now, when I build the iOS target everything is fine.
But when I try to build the macOS target, the iOS version of ViewController.h gets somehow imported and I get the following error:
Lexical or Preprocessor Issue - 'UIKit/UIKit.h' file not found
...pointing at the #import statement in Manager.m.
Some more information:
ViewController.h is a public header in both frameworks, and is included in the umbrella headers for both targets:
#import <MyFramework/ViewController.h>
Each version of the header has target membership set to the appropriate target.
For both targets, Header Search Paths and User Header Search Pathsis blank, and Always Search User Paths is NO.
I have tried to set Header Search Paths to each of the following values, to no avail:
$(SRC_ROOT)/Platforms/macOS/
$(SRC_ROOT)/Platforms/macOS/**
./Platforms/macOS/
./Platforms/macOS/**
I tried deleting the iOS version of the header temporarily, and the build succeeded. But after restoring the file and cleaning the build folder, it fails again.
How can I get Xcode to "see" the right version of the header, on the Mac target?
EDIT: I tried the same path values from point (4) for "Framework Search Paths". Same error.
UPDATE:
If I set the build setting Always Search User Paths to YES (the default is NO), my framework builds. I can even build a sample Mac app that links to it and it runs. However, I get the warning:
Warning: using 'ALWAYS_SEARCH_USER_PATHS = YES' while building targets
which define modules ('DEFINES_MODULE = YES') may fail. Please migrate
to using 'ALWAYS_SEARCH_USER_PATHS = NO'.
...but I read somewhere this would cause trouble down the line (can't find the post now).
UPDATE 2:
If, in addition, I change the build setting Defines Module to NO (as suggested by the warning), both the framework and the app that embeds it build succesfully, and the framework's classes are available (i.e., instantiable) from the app's code.
However, I fear this whole "not defining a module" business is going to cause trouble when I attempt to use my framework from an app written in Swift...?

Related

Xcode 8 with mixed Swift and Objective-c project generated "ModuleName-Swift.h" header not found

I have a project with mixed Swift and Objective-C in Xcode 8 that uses the generated "ModuleName-Swift.h" header file to import swift into Objective-c classes, but the preprocessor is not able to find the generated header file and throws an error on the import.
"Lexical or Preprocessor issue : 'ModuleName-Swift.h file not found'"
The project compiles just fine, but the preprocessor throws errors for the header not being found and for any Swift classes called inside the class there is no syntax highlighting or code completion. It's a struggle working with Swift classes in Objective-c that are unrecognized by Xcode 8, but yet compile just fine.
Any ideas on how to appease the preprocessor in Xcode 8?
I had exactly the same issue. Found the solution after adding a new file aiming to only one target (by mistake) and noticing that it had no problem reading the Swift classes. So, if you have multiple targets, and since the migration you didn't have the need to build and run them, suggest you to do that.
Have this problem when we have multiple targets. If the Objective-c Generated Interface Header Name variable in Swift compiler of newly created targets is different than the original target's value. Change it to the same value with original target. See the following:
change, newtargetname-Swift.h to originaltargetname-Swift.h for new target
To fix this issue Xcode 9.2, After long research i came to known my "Objective-c Generated Interface Header Name" is named after Product Name "productname-Swift.h"
You need to add this in your build settings.
There might be an issue while migrating to Xcode 8, where you will have unspecified in the build setting Swift header file.
This if from killerz
Go to
Build Settings->Objective-C Generated Interface Header Name
and set the value to YourModule-Swift.h (this is usually already set, this is the filename you need to import on .m file #import "YourModule-Swift.h"
If
your product's normal targets run fine, but
you get the error when running your test targets…
note that each target uses (and should use) a different filename for the Objective-C Generated Interface Header Name.
This means you cannot import the generated header file in your Objective-C .h files, because they won't be found in the test target:
Instead, you should move these #import statements into your Objective-C .m (implementation files), where they'll build successfully.
If you need to refer to Swift classes in a .h file, use the #class directive, e.g.:
//
// ViewController.h
// import-example
//
#import <UIKit/UIKit.h>
#class SomeSwiftClass;
#interface ViewController : UIViewController
- (NSString *) titleFromGenerator:(SomeSwiftClass *)generator;
#end

Umbrella Header Not Found When Changing Target Name or Product Name of Framework

I have this code base that I decided to turn into a framework to reuse in my future apps.
So I went ahead and created an Xcode Project for Cocoa Touch Framework.
To keep things simple (and workspaces out of the picture, at least until I grasp the basics of frameworks), I created a "test-bed" iOS app that embeds/depends on/links to the framework as an additional target to the same project (not a separate project). The idea, of course, is to use this app to test my frameworks capabilities as I add or modify them.
So my project has two targets:
MyFramework
MyTestApp
...And of course, two schemes (one to build each):
I am also modifying the code so that it works both on iOS and macOS.
Warning: no umbrella header found for target 'MyFramework (macOS)', module map will not be generated.
So far, so good.
Additionally, I am also modifying the code so that it works both on iOS and macOS.
So I added two more targets:
MyFrameworkMac
MyTestMacApp
...aslo setup so that the app target-depends, links to, and embeds the framework.
Still, good.
Next, I decided to do some cleanup and file rearranging, to keep things tidy and making sense before the number of files starts to grow further.
Then, the trouble started.
After some trial and error, I discovered a few things:
1) If I change the target name for the iOS Framework and try to build the iOS app, I get the following warning:
/Users/Me/Projects/MyFramework/Code/MyFramework/:1:1:
Umbrella header for module 'MyFramework' does not include header
'PublicHeaderXX.h'
...for each of the public header that are included in my master header:
// In this header, you should import all the public headers of your framework
// using statements like #import <MyFramework/PublicHeader.h>
#import <MyFramework/PublicHeader01.h>
#import <MyFramework/PublicHeader02.h>
#import <MyFramework/PublicHeader03.h>
...
2) If I change the product name of the iOS framework in Build Settings, I get the error:
Lexical or Preprocessor Issue | 'MyFramework/MyFramework.h' file not found
...pointing at the location where I import it in the app source code:
#import <MyFramework/MyFramework.h>
for the Mac framework target, I can get away with changing the Target Name, but if I change the product name, I get the warning:
Warning: no umbrella header found for target 'MyFrameworkMacRenamed',
module map will not be generated
So I ask...
Is there a way to set the target names and product names I want for each framework target?
I'm sure there must be something somewhere that I should "modify to match" and eliminate some discrepancy, but I'm new to frameworks and can't figure it out ... (What is an 'umbrella header' anyway?)
It turns out the "umbrella header" is no other than the 'main' header for the framework that is created automatically by Xcode when you first create the project or framework target, and it must have the same name as the target (as explained, for example, here).
As to why both target and product must me named the same, I can only guess it has to do with keeping linking not too complicated (Apps are not 'linked against', so I guess there is no damage in the product name being anything you want).
I was trying to get away with a Single Header to Rule Them All (platforms), using TargetConditionals.h etc. to import either Cocoa.h or UIKit.h, which is impossible, because Xcode won't let you use the same name for both targets, and those have to match the name of their headers!
So, I settled for:
<MyFramework/MyFramework.h>: Classic. Accept No Substitutes. Exclusive for iOS, and
<MyFrameworkMac/MyFrameworkMac.h>: Now Available on the Mac too! - From the People Who Brought You MyFramework
I did a lot of reading and trying. My solution is combined:
Clean build
Close Xcode
Delete DerivedData everywhere - in project folder, user folder (~/Library/Developer/Xcode) and in root folder
/Library/Developer/...
Open Xcode and clean again
Delete app from test device
Now it works.

iOS ARToolKit Xcode Implementation

I'm trying to implement ARToolKit into an Objective-c iOS app.
I have downloaded the ARToolKit SDK and I see the following contents. The ARToolKit5 directory is for Mac OSX, so I have left this one closed. ARToolKit5iOS is the directory that I have tried to import into my Xcode project.
What I have tried so far...
Inside share > packaging, I ran the following command and this seemed to run correctly without any errors.
bash ARToolKit5iOS-bin.sh
Then I tried to import the lib and include directories into my Xcode project.
The problem
Here is the contents of my project > ViewController.m
#import "ViewController.h"
#import <AR/ar.h>
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
As you can see in the following screenshot, the error occurs whilst trying to import the AR toolkit.
I am not an Objective-c developer, so what am I missing here?
Give the correct location of <AR/ar.h> file.
For example:
#import "../ARAppCore/EAGLView.h"
Here's what you do:
1. Download iOS SDK on ARToolKit's Download page
2. Unzip the archive and move the folder to where your Xcode project is in the file system
3. Open your project in Xcode
4. Drag the ARToolKit5iOS.xcodeproj into your project
5. Select your project on the left panel, click on your app target, then in Build Phase, add various AR targets as dependencies and link libraries
6. In Build Settings, under Search Paths, add "Library/ARToolKit/include/" and "Library/ARToolKit/include/ios7" to Header Search Paths. Also, add "Library/ARToolKit/lib" and "Library/ARToolKit/lib/ios7" to Library Search Paths. *
This path will differ depending on where you put the ARToolKit sdk and how you name the folder. As you can see in the phone in Step 2. I add Library folder and put everything under the folder "ARToolKit". Plus, the Library folder is at the same level as the ARExperiment.xcodeproj file. Thus, when referencing them, I have to put "Library/ARToolKit/" first.
I also integrate ARToolKit library to new iOS project after long research.
Need to add lib, include and ARAppCore to our project. Please note the following image when we add the folders to your project
You can fix the issue by adding 'Header search path' on target of your new app.Please go through the following image.
You can create a framework target and separately build a framework that you will later put into your application (which will also work with a swift app). To do this you will need to start as follow:
Download ARToolKit5-bin-5.3.2-iOS.tar.gz and unpack it.
Open ARToolKit5iOS.xcodeproj
In Xcode go to File -> New -> Target
Choose Cocoa Touch Framework, enter Product Name, set language to Objective-C, set Embeed in Aplication to None
Go to ARFramework target Build Phases, you will configure it according to ARApp target that is:
in Build Phases in Target Dependencies add: AR, ARICP, ARvideo, ARgsub_es2
in Compile Sources add: ARAppCore/EAGLView.m, ARApp/ARViewController.m, ARView.m
in Link Binary With Libraries add: Accelerate.framework, libAR.a, libARICP.a, libARvideo.a, libARgsub_es2.a
Go to Build Settings and set Automatic Reference Counting to No
Create new PCH File (prefix header) for you Framework target
In Build Settings set Precompile Prefix Header to YES and in Prefix Header set path to PCH file that you have created
In created PCH file add imports: #import <Foundation/Foundation.h> and #import <UIKit/UIKit.h>
If your framework need to be bitcode enabled then set Enable Bitcode in Build Settings of you framework target and targets: AR, ARICP, ARvideo, ARgsub_es2
Your framework target should now Build successfully so you can check Product -> Build on your framework target
Note that in ARViewController.m from ARApp that you added to the framework there are two hardcoded paths to camera_para.dat and hiro.patt files which are needed in this example to detect hiro marker. To solve this you can for example add those two files to you application and edit ARViewController.m to search them in main bundle so for example edit lines that load them in the ARViewController.m to:
char *patt_name = [[NSBundle mainBundle] pathForResource:#"hiro" ofType:#"patt"].UTF8String;
and
char *cparam_name = [[NSBundle mainBundle] pathForResource:#"camera_para" ofType:#"dat"].UTF8String;
or implement some custom reading depending on your needs. In your app on storyboard set viewcontroller class to ARViewController and thats it, framework should now work fine and scan hiro marker in your custom app and show a cube on top of it. Also note that this is just an example of how to copy ARApp functionality into framework that can be attached in your app and this framework will not have any visible interfaces so this is just the basic work you will need to do to integrate it with basic single marker detection functionality.

Importing a library in to an Xcode 7 project

So I am trying to add a static library to my project in order to interface with a scanner. I have linked the binary in build phases to the libCaptuvoSDK.a, put the Captuvo.h header file in the project folder, and finally set the project to always search the user paths and added $(BUILT_PRODUCTS_DIR) recursive to the user header search paths. After doing all this I am trying to use #import "Captuvo.h" in my ViewController.swift file and getting the 2 errors Expected identifier in import declaration, and Expected expression. I have tried different combinations of importing and none of them seem to make a difference so I am led to believe the issue is with my process of adding the library.
I am new to Xcode and have never used a third party library in an application before so I feel I may be making a simple mistake or just misinterpreting things. Any help is appreciated!
Okay so I managed to fix my issue! I had imported the static library properly but the real issue was the header file. I fixed my issue by creating a new file in my projects folder named Quick-Scan-Bridging-Header.h. Inside that file is where the #import "Captuvo.h" line belonged. Once that was done I opened the Quick Scan apps build settings and under Objective-C Bridging Header I added the path Quick Scan/Quick-Scan-Bridging-Header. I also added the Header Search Path $(BUILT_PRODUCTS_DIR)
After I did all this I am able to use the Captuvo classes in my ViewController.swift file.

Cannot call swift function in Objective C class [duplicate]

I have a project that was started in Objective-C, and I am trying to import some Swift code into the same class files that I have previously written Objective-C in.
I have consulted the Apple docs on using Swift and Objective-C in the same project, as well as SO question like this, but still no avail: I continue to get the file not found error after putting in #import "NewTestApp-Swift.h" (NewTestApp is the name of the Product and module).
Here is what I have done so far:
In Define Modules, selected YES for the app.
Ensured that the Product Module name did not have any space in it (see screenshot below question)
I have tried using #import "NewTestApp-Swift.h" inside ViewController.m, ViewController.h and AppDelegate.m but none of them has worked.
What else am I doing incorrectly? Thanks for your help.
Screenshot of settings:
Errors that I am presently encountering:
I was running into the same issue and couldn't get my project to import swift into obj-c classes. Using Xcode 6, (should work for Xcode 6+) and was able to do it in this way....
Any class that you need to access in the .h file needs to be a forward declaration like this
#class MySwiftClass;
In the .m file ONLY, if the code is in the same project (module) then you need to import it with
#import "ProductModuleName-Swift.h"
Link to the apple documentation about it
https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c
If the Swift code is inside a Module (like in your case):
#import <ProductName/ProductModuleName-Swift.h>
If the Swift code is inside the project (mixed Swift and ObjC):
#import <ProductModuleName-Swift.h>
In your case, you have to add this line in the *.m file:
#import <NewTestApp/NewTestApp-Swift.h>
IMPORTANT: look at the "<" in the import statement
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
How I managed to import swift into objective-c:
Defines Module set to YES (on project - not on target)
Product Module Name set (on target - not on project)
In your ViewController.m import the swift code with:
#import "MyProductModuleName-Swift.h"
Add a swift file to your objective-c project (File -> New -> Swift) and Xcode will create the bridging header from objective-c to Swift but this is crucial for making it work the other way around too - apparently.
For the last piece in this puzzle thanks to Swiftoverload for making me aware of actually adding a Swift file via Xcode GUI and not just dragging and dropping existing swift-files into my project for making it work:
http://nikolakirev.com/blog/using-swift-in-objective-c-project
Using Xcode 8.2.1 and if you look at Project > Build Settings > Objective-C Generated Interface Header Name, there it shows only one header file named like Product-Swift.h
This means that instead of importing each modules separately from Objective-C .m file, using individual -Swift.h file, you just import one Product-Swift.h which aggregated all Swift modules.
I encountered the same problem by looking for traditional way of importing modules separately, but the current version of Xcode and Swift 3 changed it to use only one header for all module importing.
Spent an hour on this issue, following these steps will help you to understand what's missing:
Open Xcode preference and navigate to DerivedData folder
Search for "swift.h" in finder
If you can not find any project-swift.h file, this file haven't been generated. You usually need to add #objc to one of your swift class and successfully build the app, only then will Xcode generate this file
If you found "xxx-swift.h" file, make sure your import statement contains the correct name.
I was having problems importing Swift into an Objective-C project. In the end I looked into the Derivied Data folder to check what Xcode 7 was generating. The filename was completely different to the one I was expecting.
Once I had the actual filename I imported that and the project could build.
iOS - Swift.h file not found
[Mixing Objective-C and Swift]
<name>-Swift.h should be created by Xcode automatically if Swift code expose an API via #objc or #objcMembers[About]
Usually a location looks like
~/Library/Developer/Xcode/DerivedData/
ProductModuleName-foo/
Build/
Intermediates.noindex/
ProductModuleName.build/
Debug-iphoneos/
ProductModuleName.build/
DerivedSources/
ProductModuleName-Swift.h
It can be changed by
Project editor -> select a target -> Build Settings -> Per-configuration Intermediate Build Files Path
By default the value is $(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
Importing the header file, i.e.
#import "<ProjectName>-Swift.h"
within the .h file generated an error, stating:
-Swift.h' file not found
and the build failed.
Instead use:
#import "<ProjectName>-Swift.h"
within the .m file, and even though the same error appears, running the project anyway suppresses the error.
The swift classes are then available within the .m file.
If Your App name have any special character then use _ for special character.
For Example if your App name is Name "Test App®"
Then you can import swift file by "Test_App_-Swift.h".
Space and ® is replace by _ while you are import.
Make sure your swift class has the public declaration, and extends NSObject:
public class MySwiftClass: NSObject {
//...
}
The import should work with quotes, not brackets, if the swift class is in the same project.
if you add a Swift File first, rememeber to add swift file to your target..., in the left column
Had faced the same problem with my team when was working on project using git. One developer hasn't updated Xcode to the last version (7.3) which was required for latest Swift 2.2 version. So, compiler hasn't recognized new Swift syntax and couldn't generate interface for Swift library (projectname-swift.h).
Check if Xcode version is the latest one!
DEFINE MODULES: YES
and import "ProjectName-Swift.h" in .m file of Obj-C class
This worked for me to access Swift classes in Obj-c.
I had the same problem with #import "myProj-Swift.h" not found, Xcode 12.3, the year is 2021.
It appears that unless a bridging header has been generated, it is not possible to import myProj-Swift.h.
My (reproducible) solution, when needing to add Swift to objective-C projects is to create (File - New File - Swift file) a dummy empty Swift file in my project. Xcode then asks whether to create a bridging header, to which I answer yes. This causes a "myProj-Bridging-Header.h" file to be added to my project, which is visible in the Project Navigator.
Once this is done, the error on #import "myProj-Swift.h" disappears.
After that I can delete the dummy file, and insert the needed Swift classes into the project.
The logic of generating a visible bridging header, but leaving the -Swift.h entirely invisible escapes me entirely. Never mind the challenge of trying to find out about this in the official documentation Importing Swift into Objective-C, which (to me inaccurately) states "You don’t need to do anything special to create the generated header".
It is probably a good idea to also mind the answer from #Sandeep Bhandari to this question - who says the -Swift.h file will only be generated if the project compiles successfully.
More info also in this and this question.
I ran into this problem after duplicating an existing target. When I tried to build with the duplicated target, the "ProductName-Swift.h file not found" error appears.
After going through the build settings in the new target, I found the value of the setting "Product Name" somehow is set as the same as the target name. After setting it with the correct one the error disappeared.
If your product name is TestApp-Dev then filename will TestApp_Dev-Swift.h
You can verify by going to the following location
~/Library/Developer/Xcode/DerivedData//Build/Intermediates.noindex/yourProjectbuild/Debug-iphonesimulator/MashreqMobileApp.build/DerivedSources
If you want same file name for each build schemes then go to
Build Settings to be the same across your modules/schemes. (set it to $(PROJECT_NAME)-Swift.h).
If project name is TestApp, then the file generated will TestApp-Swift.h and it will remain same across the schemes
During development, there might be a possibility that you would have any swift class that is not completely implemented due to which there might be some syntax errors.
The swift header file will be available for use only if all the swift files are error free.
Make sure there are no syntax errors in the swift files and then try to import the swift header in the objective - c file
I faced the problem with the name of project (target). It included symbol "-". So the decision was next: if name of project is "Test-App", then name of imported class is "Test_App-Swift.h"
If you have multiple target make sure that you have build all frameworks
Xcode 11
I ran into this problem when building on Xcode 11. Took me a bit to figure out what was wrong, but essentially, I had changed the "Display Name" setting on the Target's "General" tab instead of changing directly in the Info.plist file through the "Info" tab on the Target.
This resulted in Xcode 11.5 going through an rewriting/creating a bunch of brand new custom build settings and modifying the name of the app module and the built .app product. In this case the new display name also had a forward slash (/) character in it which may ultimately be why it wasn't building (see #Silversky Technology's answer).
Regardless, I resolved this by undoing all of Xcode 11.5's automatic changes to the project file and manually making the same change to the bundle display name in the Info.plist file and everything works perfectly.
I wish it would tell you that it was doing stuff like this before it just up and does it without your consent.
Target executable was missing a dependency on my (or any other in fact) framework.
Build Phases -> Dependencies must list the dependencies of a target to avoid intermittent errors: in my case debug
build was fine and automated Jenkins CI builds were failing.
A nightmare to debug considering Jenkins output produces
voluminous garbage that's a huge time pit to get through.

Resources