I have created a static iOS library using this tutorial.
The library itself depends on the SocketRocket library.
SocketRocket is included as #import <SocketRocket/SRWebSocket.h>.
When I build the library, everything works fine.
However, if I integrate my library into my sample project, the following error is thrown.
Lexical or Preprocessor Issue
'SocketRocket/SRWebSocket.h' file not found
How can the library build, but later fail to find the file in the sample project?
UPDATE
The Library has its Header Search Path set to "$(SRCROOT)/Vendor/SocketRocket/", the sample project has the Header Search Path set to "$(SRCROOT)/Vendor/MyLibrary/". If I set it to "$(SRCROOT)/Vendor/MyLibrary/**" it finds SRWebSocket.h and builds successfully. However, this includes all the SocketRocket Headers into the sample project as well and I don't want that.
UPDATE 2
I narrowed it down to the following
In the static library one .h file uses #import <SocketRocket/SRWebSocket.h> to import SocketRocket.
If I add the library to my sample project, the SRWebSocket.h file is not found.
How can I make the sample project recognise this file?
Have you made user that "Step 9: Final setup of app project" where you set your header search paths is actually pointing to the location of the header files?
Related
I am attempting to convert an old statically linked library to a framework. With mixed swift and objective c in the static library, all headers are generated correctly. However, switching to a framework target and adding swift files, marked with the #objc header, the class is not added to the -Swift.h header. I can import the header, but swift classes are not found. This is in Xcode 10.2 and attempted using both Swift 4.2 and 5.
Are there any particular settings in XCode that will affect the generation of the *-Swift.h header in a mixed Objective C/Swift framework target?
I had a similar issue. In my case it was a known issue in Xcode 10.2:
https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_release_notes
If you’re building a framework containing Swift code and using lipo to create a binary that supports both device and simulator platforms, you must also combine the generated Framework-Swift.h headers for each platform to create a header that supports both device and simulator platforms. (48635615)
...
In my case all I had to do was to update the Carthage to the newest version 0.33.0
The problem appears to be a combination of Apple's new build system, the expectations they set when compiling and the number of inter-dependencies in the project setup.
The new build system runs the Swift compilations in parallel. When having multiple library/framework dependencies that are mixed Objective C and Swift, the compiler appears to not generate the -Swift.h files on time. In static libraries, the -Swift.h files appear to be generated at the end of the Swift Compilation process, meaning they are not generated quickly enough to be used by the Objective C files when the Objective C compilation occurs. When generating a framework, it appears that the Compiler generates the header at the beginning of the compilation process and the Swift files are not fully compiled and the -Swift.h file does not generate appropriately with the Objective C class interfaces and protocols.
What this means ends up meaning is that we can not rely on the "target dependencies" to build the dependent projects correctly.
So how can we build our .framework of mixed Objective C and -Swift.h without a ton of manual scripting.
Here are the tricks I discovered that will work.
Use the old build system. When using the new build system there is an error when it attempts to merge the module map for the static library file saying that it can not find the *-Swift.h file whether or not it exists.
Create your framework by making it a wrapper around the static library by:
Giving them both the same product name and module name.
Add a single .Swift file to the framework build so that it has something to compile and will link the swift libraries.
link to the static library in the framework.
Add all necessary headers to the public headers of the framework.
Add all public headers to the umbrella header.
Use a Run script phase to copy the *-Swift.h file from the static library build to the framework product post compile.
For any public headers that include the *-Swift.h, you may need to post process the header and replace the *-Swift.h import with the appropriate framework import ie . This would not be recommended due to possible cyclical imports in the umbrella header.
When running a clean, build the framework target first manually, before building the application target.
Below is an example script for copying the *-Swift.h file post build.
header_file="${TARGET_TEMP_DIR}/../${PRODUCT_MODULE_NAME}.build/DerivedSources/${PRODUCT_MODULE_NAME}-Swift.h"
header_dir="${BUILT_PRODUCTS_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}"
mkdir -p "$DIR"
echo "copying $header_file $header_dir"
cp -f "$FILE" "$DIR"
UPDATED
Marking all modules Swift compilation mode to "Whole Module" appears to have a positive affect on this issue, but I have not fully tested it.
I have generated Objective c client from swagger.json. And imported the generated source in my Xcode project by Right clicking on project then choosing Add Files to "ProjectName". As swagger-codegen generated source has dependency on ISO8601, JSONModel and AFNetworking, so i downloaded them and added in my project. Project is building successfully but it is not working properly. When i invoke any API call by using functions inside Api folder it is unable to invoke function inside Core folder. I tried putting debug point in function inside Core folder but flow of control is not reaching there, and Xcode is not showing any error either.
Surprisingly generated code is working fine if i add it as cocoapod dependency.
But i don't want to use cocoapod in my project.
What step am i missing in importing it manually? And why Xcode is not throwing any error?
If you are importing the dependancies manually instead of using cocoapods then you have to change the import statements from
#import <JSONModel/JSONModel.h>
to
#import "JSONModel.h"
and the same for all of the AFNetworking imports
Finally i found the problem "Pheww!", Hope it may help others.
Actually i was using frameworks of all three dependencies, and app was crashing at start. I found somewhere that making them Optional in Linked Frameworks and Libraries will stop the app from crashing, and indeed crash gone.
But doing that caught me in this weird schenario.
So the solution for this problem is to keep them Required and add one New Copy Files Pahse in Build Phases and choose Frameworks in destination. I renamed that as Embed Framework.
new copy files phase
And just cross verify the frameworks, In General tab
enter image description here
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.
Now I have a project, like testApp, using some third party lib like alamofire and some others libs in objective-c.
Now I want to add a today widget. According to some tutorial, I created a new target "testAppKit" as a shared dynamic framework, and target "testAppWidget" as today extension. The common code will be in testAppKit for reuse.
Now I need to use third party libs in testAppKit. And added lib and header in build phases of testAppKit. Then I add #import <theLib/TheHeader.h> in testAppKit.h. But there is an error:
Include of non-modular header inside framework module 'testAppKit'
So, I want to know how to use third party libs (maybe in Swift or Objective-C) in this kind of embedded dynamic framework.
I use Dropbox Datastore API in my app and I finally made it working for embedded Cocoa Touch framework to share code for Containing App and Today Extension.
I figured out that in my Swift file in the embedded framework I can import any 3rd party framework I had in the Project (i.e. Farbic.framework, Crashlytics etc.) but not Dropbox.
What was the difference? The "Modules" folder! Dropbox.framework doesn't provide module map file. So I created it based on what I found in Fabric.framework:
Go to the Dropbox.framework folder in your project direcotry.
Create new folder "Modules" and go inside
Create a file called: "module.modulemap"
The content of the file:
framework module Dropbox {
umbrella header "Dropbox.h"
export *
module * { export * }
}
After doing that I needed to add import path.
Go to your Project file
Select your embedded framework target
Go to the "Build Settings" and find "Swift Compiler - Search Paths"
Add path to your Dropbox.framerowk and set "recursive" option.
I wanted to put a screenshot here but I can't do that yet - because of my "reputation" ;)
Now I'm able to do "import Dropbox" in my swift files :)
Hope this can help you :)
In my project i have following setup
Library Project - which builds to OSX framework
Main Project - OSX application
So library project is build into the framework, and main project uses that private framework.
Headers on library are all in project group, application uses header_search_paths setting to find the headers.
Now I'm trying to make the lib work nicely with swift (get the suggestions), and to do that I need to make the framework build into the module.
So I am moving the header files from project to public group. But problem now is that the headers are shipped with app, but I would like them to be not visible (as it's private framework).
Is there way to make the headers private when i ship the app, but have the module build so that i get the suggestions from swift ?
Try creating a top most header file (for example yourProject.h) which is visible and import all your header files that you want hidden into it. Then bridge that header file in your Swift project-Bridging-Header.h.