Header file not found for embedded framework inside library for React Native app - swift

I'm currently working on a contract job where I've been asked to help integrate a 3rd party SDK with an existing React Native app. The SDK only comes in Android and iOS specific flavors, meaning that it has to be added on the platform-specific side of things (in my case, the iOS side with Xcode).
For the app, the client has created a react native module which gets built into a Library in Xcode, represented by a separate nested Xcode project in Libraries/MyLibrary.xcodeproj from the root of the base Xcode workspace project. This library has several method stubs defined in React Native which will need to be implemented in Swift (and likewise in Android), as this is in these methods that the 3rd party platform-specific SDK is utilized.
The issue I'm having has to do with accessing the 3rd party SDK framework in the library's existing bridging header file. I have followed every tutorial under the sun for how to integrate external frameworks with an existing Xcode project. This includes steps about adding the framework to the project, adding it under the Embedded Binaries and Linked Frameworks and Libraries sections of the project target, adding it under the Build Phases/Link Binary With Libraries section of both the project target and the library target, and adding the framework path under Project Settings/Framework Search Paths. From here, I add the appropriate import statement to my library's Library-Bridging-Header.h file with #import <MyFramework/MyFramework.h> so I can then access the framework in Swift. (This import statement is copied directly from the bridging header file of the sample project included with the SDK, so I know it is correct and should not be given in a different format such as quotes instead of angle brackets).
Regardless of following all of these steps multiple times over and in various combinations, I still get this error at build time: MyFramework/MyFramework.h file not found.
To clarify, MyFramework is just an alias for the actual 3rd party framework I'm attempting to integrate, and MyLibrary is an alias for the existing library with nothing but method stubs given to me by the client to implement in Swift.
Again, I have read every tutorial and forum under the sun, but none seem to address this very specific issue of integrating a 3rd party framework in a xcodeproj Library within the iOS version of a react native app. I would appreciate any new insights or suggestions anyone might have to offer! And please, please don't just post a link to or copy the steps from existing forum posts about a similar-sounding issue, as I've probably already read it 😉. Understand that I think that there is something subtly unique about my specific circumstances which are causing these same steps from the 10+ articles that come up on the first page of Google and StackOverflow NOT to work.

Figured it out! I'll post my solution here in case anybody out there ever runs into the same issue as me.
TLDR - You must add the 3rd party framework in the root of the xcodeproj Library (NOT the top level project) AND ensure that the files were actually copied into that directory, not just referenced from the directory you copied the framework from (be sure to double-check in Finder, since checking the 'Copy if needed' box doesn't always work for some reason). Then, you must add $(PROJECT_DIR) to your xcodeproj Library's Build Settings/Framework Search Paths, and also drag and drop the framework from the root of your xcodeproj Library into the Library's Build Phases/Link Binary With Libraries panel.
I'll address some of the issues with other tutorials/forums that I found, with hopes that it might help someone else that finds themselves as frustrated as I was in this position.
Most only address adding the framework to the base level project, not the obscure case of a project within a project. Therefore, when you start following the steps, it can be confusing to know whether you should be changing the settings of the top-level project or the sub-project. Again, as I discovered, all changes should ONLY be made to the sub-project.
There are a few tutorials that do seem to address this situation regarding a project within a project, but the steps describe adding the framework to the top-level project under Embedded Binaries and Linked Frameworks and Libraries, but I believe the situation described in these tutorials are somehow subtly different than this situation here. Again, only mess with the sub-project.
There's a lot of discussion out there about "umbrella frameworks", but that doesn't really apply to this situation, and again, the terminology similarities can make it seem like it's a similar issue. As I understand it, "umbrella frameworks" are discouraged by Apple, but again, this situation is not the same.
Sorry for the long-winded explanation, but I'm hoping to provide the kind of detail I would have liked to have found when I was searching for solutions for this weirdly obscure problem.
Cheers!

Related

how to build a custom framework for pure swift in xcode 7

I want to build a custom framework in pure swift. Then I want to export that custom framework and import it into another pure swift app project. I want to do this by linking to the framework in the "Link binary with libraries" build phase. Seems straightforward but I never get it working in this particular approach.
I have googled for solutions and tried out some things. However I don't want objective-c interoperability. It's all pure swift anyway. Also I don't want to create an app project and then add embed a framework in to that (what is the point of this anyway?). Neither do I want to reference the framework project (by dragging the framework project into the app project). And I certainly don't want to create a workspace. All the solutions I found fall into one of these categories.
Every framework and every app I work on should be contained to its own little project universe.
Thus far I am stuck at the errors "no such module" and "linker command failed with exit code 1". A link with step by step instructions would be appreciated or any other advice you might have pertaining to this issue.

Building pure Swift Cocoa Touch Framework

I'm exploring Swift with Xcode-6 and so far so good although I think the new collections need a little bit of work as I've managed to break the compiler a few times.
Problem is I'm now stuck trying to create the framework package to then use in another project. The project builds without issue and all tests pass successfully. When I go to create Archive (which I assume is what is required) I receive the error:
:0: error: underlying Objective-C module 'Sample' not found
Now I assume this has something to do with the contents of my Sample.h which tells me
// In this header, you should import all the public headers of your framework using statements like #import <Sample/PublicHeader.h>
which is fine except I have only used swift enums, structs and classes for this framework so therefore no .h files exist.
Can anyone shed some light on this one as I can't find any documentation available yet?
EDIT (7/27/2018)
The information in the answer below may no longer be accurate. Your mileage may vary.
I sat down with an engineer and asked this exact question. This was their response:
Xcode 6 does not support building distributable Swift frameworks at this time and that Apple likely won't build this functionality into Xcode until its advantageous for them to do so. Right now, Frameworks are meant to be embedded in your app's project, rather than distributed. If you watch any of the session videos or see the sample projects, this is always the arrangement. Another reason is that Swift is very new and likely to change. Thus your Swift-based framework is not guaranteed to work on the platform you originally built it on.
Slight Update
The engineer mentioned that it's not impossible to make a framework for distribution, just that it's not supported.
I was able to get past the error by going to the target for the framework and on the Build Phases tab under Headers, remove the MyFramework.h file
However I was getting the "Underlying Objective-C module not found" error when I was using a framework to share code between a containing app and an app extension, both of which were pure Swift.
Assuming you are creating a truly pure Swift module, you must disable the Objective-C Compatibility Header and any generated interface headers so the compiler doesn't go off assuming it can find an Objective-C module for the framework.
Do Not remove your public framework header. You'll get a module-map warning at link time if you do.
You might find this useful: Creation of pure swift module
In short: it's possible to make static framework, but there is one issue: it doesn't work in end user' project if "ProjectName-Swift.h" header included.
But, it works fine if you use only swift.
I think it's a bug in XCode 6, or that Apple does not allow archiving the Framework from XCode while in beta.
If you compile to profile XCode generates the framework correctly. (See the Release folder created in DerivedData)

iPhone static lib

i want to share some code with other iOS projects. So I create static library.
When I use this library in other projects and use header file from that lib I get an error like No such file and Directory. Can any one tell me fixes of it.
Here I get reference for making static lib
http://www.amateurinmotion.com/articles/2009/02/08/creating-a-static-library-for-iphone.html
I downloaded that sample. It is also not working in my case. So please help me to fix that error.
Thanks in advance
My guess would be because the blog, whilst detailed, is probably a bit old now. Like anything there's a thousand ways to skin a cat.
You can now create frameworks for the iPhone sdk and include both simulator and device versions of the classes. Frameworks have the advantage that they can simply be dragged and dropped on Xcode to include them in a project. In addition I like to store my frameworks in version numbered directories so if I make changes, dependent projects can still use the old ones until I'm ready to update them.
I don't do it, but for the above reasons I'm not sure I'd drag and drop a libs project on a client project. To me the idea of a static framework is that it's independent on it's clients. Dropping it into client projects makes a connection between the two projects that is too tight.
Anyway do some searches on lipo and static frameworks. I also have so scripts in my project at https://github.com/drekka/dUsefulStuff that you mint find useful.

Considerations for including library as binary vs source

I'm trying to write an SSH client for the iPhone, and I'd like to use the libssh2 open source library to do so. It's written in C.
How should I include this C library for my iPhone app? Should I compile it into some binary that I include into the my app, or do I add all the source to my project and try to compile it along with the rest of my app?
I'm interpretting this question as:
"Should I compile the C library code once, and include the binary library in my project? Or should I include all the source and compile it every time I build my app?"
It depends. One of the projects I work one depends on several external libraries. Basically, we have a simple rule:
Do you think you will need to change code in the C library often?
If you will be changing the code, or updating versions often, include the source and build it with the rest of your project.
If you're not going to change the code often or at all, it might make sense to just include the pre-built binary in your project.
Depending on the size of the library, you may want to set it up as a distinct target in your project, or for even more flexibility, as a sub-project of your main project.
If I was in your place, I would build libssh2 ahead of time and just include the binary library in my iPhone project. I would still keep the libssh2 source around, of course, in case it does need to be re-built down the road.
I have an iPhone app that is 90% c. I have had no problem adding 3rd party sources to my project and compiling. I am using Lua, zLib, and libpng with no modifications. I've also included standard libraries like unistd and libgen and they just workâ„¢
The Three20 iPhone library has a great howto on adding their library to your xcode project. Give that a shot.
I think you will find in the long run you will be better off building it into a standalone library and linking it with your application. This makes it easier to integrate into future apps. Another benefit is that it encourages code separation. If you feel pretty confident with the library, you can link your debug exe to the release build of the library and get some extra performance.
I can't really think of any downsides to creating a library, after the initial cost of setting it up, and having an extra project to modify if you have some changes that need to be made to all your projects. Even if you don't know how to make a library for the iPhone, this is a good excuse to learn.
Just adding the source to you project should work fine as well.

Best way to share iphone and mac code between projects

I realise that the view/controller stuff will be different between Mac and IPhone apps but the model code may well be similar/the same. So whats the best way to organise a project(s) so that the model code is/can be shared?
Copy/paste - just duplicate it and manually keep it in sync
Have 2 xcode projects point at the same workarea - one for Mac and one for IPhone and share the code.
Common library - presumably you can't do this (or can you)
Thanks for any tips.
There are a few ways to do this. The first thing you can do is is create a project that builds as a framework on Mac OS X. Since you cannot use frameworks on iPhone, you can make static library target that contains the same code files. That basically works, but the header paths will be different. If you want the header paths to be the the same (i.e. <Myframework/MyFramework.h>) you will need to modify the the install path of the static library headers so that they are copied into "$SDK_ROOT/usr/local/include/MyFramework", and make sure /usr/local/include is an included header search path. You will then need to install the library and headers into each SDK_ROOT.
I started out doing the above, but I found it to be a royal pain. So I ended up doing something that is a variant of #2. Basically, I get the header paths to be equivalent by making a directory named "Externals" in my iPhone project root, then a directory named with the appropriate name ("MyFramework") in the externals folder. That is the folder I copy I drag the framework files into.Findally I add the Externals folder as a system header path (which is admittedly sort of a gross hack). You need to manually add new files to the iPhone project, but I have found that to be less of a pain the installing static libs into my build root.
I'm not sure if the suggestion from the previous answer would work. If you look at my previous question, you'll see that I've failed to load a custom framework on the iPhone even though the framework works fine on Mac.
I would go with method 2.
You could develop your application in JavaScript, CSS, and HTML. You would use the WebView and UIWebView objects on the Mac and the iPhone respectively. You can do pretty much anything you want in the WebView objects, even make calls down to Objective-C.
The QuickConnectiPhone installer, found here https://sourceforge.net/projects/quickconnect/, installs QuickConnectMac and QuickConnectiPhone templates into Xcode.
This way you can quickly create an application in one environment and then migrate the view to the other. In fact the QuickConnect framework is highly modular.
If you don't want to develop in JavaScript the same modular framework is found on the Objective-C side of the templates installed.
It should make it much easier for you to do what you are attempting.