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

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.

Related

Organizing Different Versions of App in Xcode

I'm developing an iPhone app that can edit images. Ultimately, I want to have a small version that allows the user to simply edit their images, and a large version that allows social networking of the images. Then I'd like to develop a version of each for the iPad.
Being that this is my first foray into commercial mobile development, I'm confused about how to organize all these versions in Xcode. Obviously, there will be file reuse shared between each version. I guess my question is, how do I go about organizing these separate projects in the most efficient way so that they share files and so when I edit a particular file that is shared, the changes are made to each version of the application? Is there some kind of construct to follow in XCode?
Are there any links or literature on how to go about doing this? (was not sure the correct term to search for it).
Remember: If you find yourself repeating/duplicating something, suspect that you're doing it wrong.
Your Xcode project will have 4 targets in this scenario. The basic target layout for this setup looks like this:
A Static Library (for your shared source files)
A Resource Bundle (for your shared resources)
App-Full (Universal)
App-Lite (Universal)
The apps link to the shared static library, and copy the resource bundle.
Naturally, apps will have sources/libraries/dependencies which differ -- those go in the app target (or some other dependency).
Given your background: Plan on it taking a good amount of time (initially and as you go) and patience to figure out how these dependencies should be composed, used, and maintained.
I would suggest keeping the "lite" and "full" projects separate but within the same workspace. That way you can keep the shared files in one project and simply use a shared reference to them in the other. All changes made to the shared files from either project will affect both.
As far as iPhone/iPad versions, I would also suggest that you keep these apps completely separate but within the same workspace (so that they can share code) as well. If you look around about the suggestions for managing both apps in a single project (aka, universal app), the only real benefit is that customers can buy one app and can download it on either device and some may get upset if that isn't available to them. If your app is free, don't worry about it.
Lastly, a caveat about workspaces, you need to uniquely name your files across all projects. For example if you're working with a project that uses a MainViewController.h subclass and another project that uses a MainViewController.h subclass, you could assign or edit the wrong one by accident regardless of what project you're in, so be wary. If using unique file names is a problem, you can bypass using workspaces by simply creating an empty project to dump all of your shared code into and then add references to your standalone apps from there.
If you choose to keep various copies of your project for different functionality, it will be eventually confusing, as there are places when XCode offers you one thing instead of another. One such place is - when you open a project from location X, it will also show you your copy from location Y since you opened it last time. As a result, you are likely to commit more mistakes. Organizer is one more such place where you can make mistakes.
XCode is self-contained enough to maintain both iPhone and iPad versions. You will have two separate storyboards which can be made part of one project if you chose universal as the type of app.
As for various features, you shouldn't be maintaining separate copies of your project. Instead, recommended way is to keep all features within single project, and have app logic provide access to various features.
XCode keeps version of your build under Targets section when you click project. To maintain multiple versions through your dev cycle, use source code repository (git or svn).

With Xcode 4, what is the proper way have a main project + a shared code project?

Currently I have an iPhone app that is just one large project. It has hundreds of code files. I have one folder called "Helper" that includes all of my classes that I have created. I'm going to be making a second app that also needs to use the exact same code that is in the "Helper" folder.
What is the proper way to share that "Helper" code between two projects/apps? Should I put it in its own project file and then add both the main app + "Helper" to a common workspace? I'm not interested in making static libraries or anything... I just want the code segregated somehow.
I've already tried making a second "blank" project file and dragging the code into it, but when I try to build Xcode just thinks I am missing header files now... for some reason it's not seeing the code in the other project.
It would be ideal if there were a clean distinction between the shared code and the code unique to your current app. If there isn't yet, try to make sure everything that will be shared is not dependent on anything from the code unique to the project.
One way you could accomplish this is by using a Git Repo and then making the shared code its own repo project. Then, in the repo for both projects, include the helper code as a submodule.
I've worked with projects that use submodules, though I haven't set up the submodule aspect myself as of yet. The benefit here is that any changes you make to "helper" can be pulled into the both projects, so the changes are synchronized.
If you aren't familiar with Git yet, I recommend getting familiar. Setting up a Git repo on your computer, even if you aren't collaborating with others, is pretty useful. XCode currently offers the option of setting up a repo when you create your project. If you haven't done that, or aren't sure though, you can still create a repo after the fact.
I use source tree to manage my repositories. Creating a repo is pretty straightforward and easy from there SourceTree. However, you can use GitHub's own desktop client, or any other client if you wish - depending on how you set up your project.
Some information about setting up a submodule in git: Setting up a submodule
So, to recap:
Make sure your "helper" code can stand on its own
Put the helper code into its own repo
Include the helper repo as a submodule to any project you want the code in.
Hope that helps!
It sounds to me the situation you have described is exactly what a framework is designed to solve. What you would likely end up doing is creating another project with all of your shared code within it and creating a framework which your applications could link against.
I would suggest reading Apple's Framework Programming Guide. From the introduction to the guide:
Mac OS X makes extensive use of frameworks to distribute shared code and resources, such as the interfaces to the system itself. You can create frameworks of your own to provide shared code and resources to one or more of your company’s applications. You can also create frameworks containing class libraries or add-on modules with the intention of distributing them to other developers.
You can put the shared code in a separate folder and then add it to the both projects.
But don't forget to add the path of the folder to the User Header Search Paths in Build Settings > Search Paths.
I'm not interested in making static libraries or anything...
Yet, for iOS, a static library target is exactly what you'd use.
No workspace required, just a separate Xcode project with that shared static library, which both apps reference.

iPhone SDK static library versioning

I've been writing iOS apps for some time now and for this particular project, I decided that I needed a static library for code sharing purposes.
I've followed some tutorials in creating static libraries and everything works perfectly.
Now I wonder, is there any way of versioning the static library?
I couldn't find any files regarding version number in the static library project, nor any good search results (both Google and here) regarding this particular issue.
I think I could create some kind of "fake" Info.plist and store the version info there.
Is that the way of doing it? Any other approaches to the problem?
Edit:
I think I may have not been clear on my purpose:
I have a workspace that has both my library project and related projects using the library, which is imported using the .xcodeproj file, then configured the dependencies so it builds whenever needed.
I just need some way of versioning the library, so that I can include that in some sort of about box, just in case.
I think you should stay away from bundling binary builds of your own code. Unless you're building a really, really, really massive library, you're better off just importing the code in any of your projects, and rebuilding it each time. You can put it in a separate target though, so Xcode doesn't rebuild it all the time.
You might want to write a tool that takes version info in a .plist and writes it out as literal strings defined in a .h file, which you can then include in your own code.
To make it foolproof (avoid mismatch between the header and the library), define a class method like [YourLibraryClass versionString] that returns a NSString with the version number or signature.

Exposing headers on iPhone static library

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.

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.