Exposing headers on iPhone static library - iphone

I've followed this tutorial for setting up a static library with common classes from 3 projects we are working on.
It's pretty simple, create a new static library project on xcode, add the code there, a change some headers role from project to public. The tutorial says I should add my library folder to the header search paths recursively.
Is this the right way to go?
I mean, on my library project, I have files separated in folders like Global/, InfoScreen/, Additions/. I was trying to setup one LOKit.h file on the root folder, and inside that file #import everything I need to expose. So on my host project I don't need to add the folder recursively to the header search path, and would just #import "LOKit.h".
But I couldn't get this to work, the host project won't build complaining about all the classes I didn't add to LOKit.h, even though the library project builds.
So, my question is, what is the right way of exposing header files when I setup a Cocoa Touch Static Library project on xCode?

I ended up setting up a LOKit.h on the project root folder like this:
#import "Global/LOCommon.h"
#import "Additions/LOAdditions.h"
#import "View/LOCustomView1.h"
#import "View/LOCustomView2.h"
And on my host project I set the header search path variable to my library's root folder, without recursion. Whenever I need to, I just import LOKit.h.
I also included on this library project common libraries (like JSON, FBConnect and Reachabillity) that were shared across projects. This way I only need to update those libraries in one place, once.

When using static libraries I usually go one of the following two ways:
If I created the library myself and it is somewhat tightly coupled to the project which uses the lib, I usually create a source root for the library in the XCode settings. Then you can add the source root as a variable to the header paths recursively.
On the other hand, if the library is either not by me, or is maintained entirely separately from my project, I usually copy a version of the library plus the relevant headers to the project using it and reference those. This is a bit more cumbersome if you need constant updates, but does not break your application if something in the library changes.

Related

two projects in xcode4 workspaces (#import failure)

I'm really struggling to get this to work in xcode 4.
I have one project that I will reuse in many applications (networking) so I create a workspace and add my two projects. So far so good....
This is where it fails..
#import "JSONRequest.h"
For no apparent reason. It auto completes the file name of the header file. I thought this had something to do with the "scheme" (also new in xcode 4) so I've tried to add my networking target in the build phase. Changing order of them... set "Shared" under Manage schemes.. I've tried so many different combinations of the settings without any success.. And the error message is get is:
JSONRequest.h: No such file or directory
If you have a clue, please let me know.
You can add the header or source folder of your project you're referencing to your Header Search Paths.
Click on the target that's importing JSONRequest.h.
Click on Build Settings.
Enter "Header Search Paths" into the search box.
Double click on the value cell.
Click the + sign.
Set the path to the project you're referring. Let's say it's called JSONlib. The path is relative to the root of the referring project (the project that's using JSONlib). For example: ../JSONlib/src/headers/ or wherever it is that the .h file lives.
Click done.
Clean and then build.
You'll find more info about this problem in the apple developer forums. Best of luck.
What are you really trying to do?
If you have an entire Xcode project you intend to share between different products that usually suggests your project builds one or more targets (such as a framework, etc.). Therefore, your "shared" project should be able to build the framework on its own, irrespective of the workspace it's contained in, right?
Let's assume it's a framework. In most cases, Xcode can figure out the dependency by simply adding the framework product to the Link build phase of the (assumed) app using the framework. Done. Xcode should know to build the framework project's target first, since it's linked against when building the app project's target.
So your problem is likely just a matter of knowing where Xcode is looking to find files. Since projects within workspaces share that workspace's build folder, they can all "see" each other. But in the case of a framework, A simple import by file name won't cut it. You'd need:
#import <MyNetworkingFramework/MyNetworkingFramework.h>
Since you're including a specific header (JSONRequest.h) (which must be one of the public headers in the framework target's copy headers build phase), you'd need:
#import <MyNetworkingFramework/JSONRequest.h>
If your "shared" project is not a framework, you'll need to amend your question to include a more thorough description of your two projects and their targets.
This worked for me,
In build settings --> Header Search Path --> Add below entry
$(SRCROOT) and mark it as recursive. If above not worked you can also try following way, <path-of-other-project> and mark it as recursive. Hope this helps to you ! (You may require to clean or restart the workspace)

XCode: Linking projects inquiry

I have 2 projects and I want to use in the first project, a class (i.e. view controller) of the second. Instead of importing all the files of the second project in the first one, is there a way to link it like a framework or library?
I tried the following unsuccessfully:
Dragged-dropped SecondProject.xcodeproj and checked SecondProject.app as a target
Added it as a dependency project in the first project dependencies
Pointed to the header files by adding in the "Header Search Paths" a path pointing to the second project which I copied in a subfolder of the first project.
When I include "SecondProjectViewController.h" I get no errors but when I try to instantiate it I get the "OBJ C referenced from" error.
Any help is deeply needed and appreciated! =)
F.
As an experienced developer I would suggest not sharing code this way across projects. The simple reason is that changes in one project will then directly effect other projects, often rendering them un-compilable. For example, if you share a controller class and decide to implement a change with a new import, then any project that uses that class will be broken until you open then in xcode and ensure that the imported class is available.
A better method is to compile your first project as a static library or framework. I'd also recommend ensuring that it is version some way. For example, in my projects I create static frameworks and store them in a directory called "v0.0.1", "v0.0.2" etc.
The framework can then be dragged and dropped into a second project to use it. The second project then refers to it via the directory path. The advantage of doing this is that if I then change the first project, the second one if not effected by the changes until I choose to update the frameworks path.
Sharing files between projects will work for small cases, that being 2 or 4 projects, but once you have more than that it rapidly becomes un-manageable.
You have only a few steps to go:
4) in First project, click the disclosure triangle in the Groups and Files section for the Second Project reference. this will display the targets of Second Project.
5) Drag the target reference (e.g., static library) from Second Project to the target in First Project's link phase.
That should clear up all the linker errors for the symbols which exist in Second Project's library. Of course, you'll have to remove those sources (based in second Second) which are compiled and linked from First.
Managing static libraries for huge codebases is dead easy this way (although I prefer the build up to the minute (as well as several build variants), and don't reference archived binaries as Derek does). Learning to minimize changes which break builds takes time to learn. dynamic libraries are a bit different - depending on their distribution, you may want to version (as Derek outlined). It's good to share, but you should put the shared exported symbols in a library, which is a dependency of both apps. Just be careful not to add too much unnecessary objc symbols to the library - objc symbols and their references cannot be stripped from the final executable and they will cause runtime collisions if they appear in two images (dylib, app, static lib) within the same process.
You can add the view controller's files to your 1st project regardless of where they are on disk -- the project will make a reference to their location.

Add external project to my iphone app in xcode

Just starting to poke around iPhone development. I am trying to add an external project/library to mine (specifically the ASIHTTPRequest, http://allseeing-i.com/ASIHTTPRequest/).
I am at a bit of a loss as to how I go about actually adding this dependency to my project. I come from a Visual Studio/C# world, and in Visual Studio I know I would "Add Existing Project" to my solution file and then add a reference to the new project to my own. Or, alternatively, reference the DLL directly if it is already built.
The ASIHttpRequest project is on GitHub, and provides full source code. I just don't have any idea about how to actually get this dependency into my own project. I tried "Project -> Add To Project", and just selected the folder ASIHTTPRequest extracted out into. I see it as a sub-folder to my project now... but get a ton of build errors. I removed everything but the .h and .m files from this subfolder, and now I don't get any build errors from those resources anymore, but trying to reference a ASIHTTPRequest object in my own project gives "undeclared" errors.
Am I missing something here? Can I not of these .h and .m files in subfolders?
You're on the right track. You just need to #import the ASIHTTPRequest header in the file where you want to use it. You do have to make sure you've met all the dependencies specified on the ASI site, but once you've done that, everything should work right by just doing an import like you've described. Once all that is set and everything is compiled, add this:
#import "ASIHTTPRequest.h"
to the top of the file where you want to use the library.

What is the recommended way to reuse utility functions among apps in my Xcode based iphone apps?

I have some utility functions like:
void myVibratePhone()
{
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate) ;
}
that I'd like to use across all my projects.
In C, I'd give each project the header file, and link in the .OBJ file (or perhaps create a library).
What is the Apple-approved recommended way to share code (cocoa and C primarily) among my apps? Would I need a framework for this? How would I go about creating one?
Also, since I'm using subversion for version control, if I use a framework, do I place the version of the framework that the app is using in the subversion repository for the project so that anyone who checks it out can build it straight away or make it a requirement that people check out a project + check out the utility functions also for a successful build of any project?
I don't plan on putting anything on the App Store at this time, but I don't want to do anything that will cause apple to not accept an app in any case.
I found this writeup about xcode 3.0 (I'm using Xcode 3.2.1):
How do I create a bundle of reusable code in Xcode?
I followed it, but am having one issue:
1) trouble finding my library .h file in the main project: I've tried both hardcoding it in the main projects .h file
#import "file://localhost/Users/piesia/Documents/My Utilities/MyUtilities.h"
as well as:
#import "/Users/piesia/Documents/My Utilities/MyUtilities.h"
and
#import "~/Documents/My Utilities/MyUtilities.h"
I've also tried updating Header search paths in the Project Build settings:
"/Users/piesia/Documents/My Utilities/**"
when using #import
After a lot of trying (and replacing %20 with space), I was only able to get the variants
#import "/Users/piesia/Documents/My Utilities/MyUtilities.h"
and
#import "../../My Utilities/MyUtilities.h"
but I'd prefer not to hard code the path if I can figure out a better way.
So, in closing, 1) is the writeup that I'm following the recommended way to do shared code in Xcode 2) is it recommended that I keep the shared files in a separate subversion repository from the main program and link and include it in as I'm doing now and 3) do you know what I'm doing wrong in my attempts at loading the shared header file? Would anything that I'm doing or not doing with shared code hurt my chances of getting approval if I ever decided to submit it to the App Store?
I agree with creating a static library to share the code.
To add the headers to the project you need to set the "User Header Search Paths" to the location of the .h files.
You then import the headers using something similar to:
#import "YourHeader.h"
You shouldn't need any additional path information in the import if the header search path is set correctly.
Oh this one is a bugger! - I think unfortunately the easiest way is to hardcode.
My team has dozens of reusable components in our products, many of them shared between Mac and iPhone. My experience in this is that most of the time it's much easier to just include the source code rather than to create a separate static library. The separate project for the library adds a lot of complexity and seldom provides much value. Here is how I usually approach it:
In subversion we have a directory tree like this:
/common
/Component1
/Component2
/Project1
/Project2
...
In Project1.xcodeproj, we just drag in "Existing files" from common into the tree (don't copy). Doing it this way avoids lots of overhead in managing another project. This does mean that changes to the common tree can break any of the projects. That means you need to recompile everything before committing (we use a top-level build script to check that you didn't break anything). The advantage of the static library is that you can stage this by upgrading the library for each project when it's ready. On the other hand, it means that you have to rev the library often and manage syncing it around. We've found that just sharing the code directly typically is much more effective.

Can you reference Xib files from static libraries on the iPhone?

In my app, i currently have all my code separated into a static library, to make it easier to set up the xcode project targets for the actual app and for unit tests for my code. The problem with this is that i want to put most of my xib files in the static library as well, but it seems that when i run my app and try to reference the xib it can't find it unless it is included in the actual app's target instead of the static library target. Is it possible to have xib files and other resources included in static libraries that can be referenced by code in that same library, and if so, how?
No it isn't possible, because a static library is not the same as a "bundle".
A bundle is a directory that may contain all manner of files including resource files (xib), executable files and static libraries. It exists on the filesystem as a group of individual files.
A static library is a single file that contains classes, code and variables that were linked together by the library creator. It does not "contain" other files, it is essentially a database of compiled code.
Although it would be possible to put the data for the xibs in there, Xcode would have no way of knowing that it was in there, as it looks for them as individual files on the filesystem.
In Mac OS, you may create a "Framework" which is essentially a bundle of code, resources, settings etc which may be reused by multiple projects. However, Apple does not seem to support custom framework creation for iPhone OS.
Bundles
https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1
Static Libraries
http://en.wikipedia.org/wiki/Static_library
Reply to comment (won't fit in comment box)
No worries, I've been trying to do pretty much the same thing as you for the last week - I'd like to ship a "framework" of xibs, include files and .a libs to a client without giving them all the source code. I couldn't find a good way to do this with bundles either.
For whatever reason, Apple are being particularly obtuse about this - I can't see a reason for them to be so in the case of static libraries (dynamic libraries fair enough).
My solution for now is to manually create a package folder "Foo" that contains the following subfolders:
"include" -> put .h files here
"res" -> put .xib files here
"lib" -> contains "iphoneos" & "iphonesimulator" subfolders each with libFoo.a
Then zip this up and send to the client. The client then:
Unzips the package where ever they like.
Adds the "res" folder under the resources group.
Changes the following target settings:
Other Linker Flags = -Objc -lfoo
Header Search Paths = /include
Library Search Paths = /lib/$(PLATFORM_NAME)
I can probably automate the package creation with some build steps at my end, but the client is stuck with four slightly fiddly steps to get set up.
I found a perfect solution for this that does all the above automatically and more
https://github.com/kstenerud/iOS-Universal-Framework
Its an xCode plugin
It worked for me like a charm,
It works only for XCode 4 and above
Yes You can. add a xib file in your library as you would do for any normal project. Then in library project target add the xib file in copy Files section along with .a file.
In your main project where you are using the library, drag and drop the xib file where .a file for library is located.
Answer in including Xib files to your static library.
This time we have Xcode 11, you just create a bundle target in addition to your library target. The bundle template is available on macOS. Then from the library code, reference the bundle to be able to reference the nib. You distribute the library with the bundle.
A detailed video about using Xibs with static libraries below:
https://www.youtube.com/watch?v=WQI02KR9kQw
When distributing you could also create an SDK. JSON.framework did this in their SVN, and I successfully replicated this. You can see how this was done in http://hltypes.svn.sf.net/ in the hltypes-ios.xcodeproj and the iOS folder in the project.
Primarily you need to "install" into your build folder, and then you need to copy the specially formatted SDKSettings.plist. Then add the path to the SDK into "Additional SDKs" list in application project. Downside of composite SDKs are the need to restart Xcode 3.x whenever this mini-SDK is updated, and Xcode's insistence on constructing a composite SDK created from Apple's base SDK and your mini-SDK (which means you need to wait quite a bit).
Application project still needs to have .xib and other resources manually added.