I have some shared code I want to reuse in my Xcode projects. The easiest way is using a shared framework. I must make headers public in order to reuse the framework in my projects.
Now: since the framework must be copied inside final products, is there an automatic way to prevent public headers from being copied too? Of course I can do this manually, but an automated trick would be amazing :)
Thank you
IIRC, you can do all that with frameworks. Frameworks can be installed system-wide, or inside the application package. If you haven't read it yet, it's in the docs : Embedding a Private Framework in Your Application Bundle
Basically, you're going to make two variants of your framework, one for developing client applications, one for embedding inside those applications. In Xcode you can :
either setup two framework targets, and change the Header files' roles as wanted (public or private)
or use the PUBLIC_HEADERS_FOLDER_PATH build setting with different values in two build configurations. (Say, "Development" and "Deployment"). Your header files will end up in different locations this way.
I haven't done this for a long time, but I don't have particularly good memories of embedded frameworks. What type of code are you reusing exactly? Is this common, all-purpose code? Or is it a whole, coherent project?
If you're just trying to reuse generic code, you might be better off using a simple, old-school .a static library with a headers folder, or even better, a static framework. (Which is just a static library inside a framework bundle)
Related
I have created a number of re-usable classes that I use across xcode projects, for example:
Utility
EmailController
MarketingController
FlashLightController
etc
I had been simply copying these class files from and back into a central repository, but now I have a number of apps it is all getting a little confusing from a config management point of view. So I was looking for an alternative.
I started investigating Static Libraries but they seem to be quite a lot of more effort for simply re-using code (e.g. different libs for device vs simulator, still having to have copies of .h files, etc).
Does anyone know of a decent alternative for quick and easy code reuse?
Thanks, Charlie
You can put the code files into a project without actually copying them into the project. In other words, just keep the class files in a completely separate location. Import them into many projects, but uncheck the option to copy them in. The projects will still refer to them successfully. Now a change made in the class files will propagate to every project that uses them.
Also, consider whether workspaces will help you.
In my view, almost anything is better than making a library or framework!
Static libraries would probably be your best bet, as I have used them and have found them to be pretty easy to use. (I haven't had to use different libraries for device or simulator, mine works on them all). Having the header isn't that annoying, and static libraries are really the only way (outside of dynamic libraries, which are banned by apple) other than copying the files to reuse code.
I have a library that I created which I would like to use the included classes across a few different projects while maintaining the library code independently. I would also like to be able to easily share it with other developers and have them easily implement it. At this point it doesn't need to be a static library.
What is the best method to do this? I have seen other devs put their classes in a brand new XCode project then import that, but what is best practice?
I think the best practice is to create a project with a static library target. Other developers can include it as a subproject in their projects.
Second best would be to simply make a directory of source files that can be included in a project on an as-needed basis. This is useful for general purpose utility code where a particular project may not want all of it.
In both cases, the library code should belong to its own git repository and included in a project as a git submodule.
If it will ever become a static library, it's best to make it one now, rather than waiting until it is "ready"; by the time you decide to switch it over, a few projects will already be using it, and converting each of them to use it will be a pain. Just do it the right way from the beginning.
If you want to distribute the library without source, you will want to use lipo to build a universal library that contains both ARM and x86 code. Unfortunately, Xcode doesn't make this as easy as it could be, but it's not too difficult with some light shell scripting.
As far as I know you should create a new project and that project to any other project you want use library in. Then link the projects and you can access it. The other way which I have done also, copy the library classes directly to the new project and access the library through importing the needed classes. In my case i found creating a project and linking it with the new project is the easiest. although copying the classes isnwhat we all do when using external libraries such as cocos2d. As far as sharing it with others, just upload it to github another place of your choice so it can be used by other dev's. I hope this helps you.t
I don't know how mature the code is, but since you specifically mention wanting to share it with other developers, you may want to investigate CocoaPods.
I'm new to objective-c & osx architecture. I started playing with building a framework and then using it. I followed this great tutorial.
During the tutorial, I had to set the framework's target's Dynamic Library Install Name to #rpath/MyFramework.framework/Versions/A/MyFramework. My understanding is that #rpath will expand to the loader's (consumer's) run-path search paths.
It seems as if the responsibility of loading the framework is split between the framework author and the consumer author. Could someone please explain why the author of the framework needs to be concerned with the consumer's run-path search path? For example, if the framework-author set the Dynamic Library Install Name to point to some random directory (instead of #rpath) how would the client be able to consume the framework?
Thanks in advance.
It depends a lot on how the framework is being used. And it's important to remember that the framework construct has existed for a long time on the platform.
For a system framework, such as the ones that Apple creates, you're going to be quite happy that they keep the frameworks in a known location. In those cases, the paths that they use are fixed for the OS, and it guarantees that you don't accidentally load the wrong one. Further, as indicated in the Framework documentation, these frameworks are loaded only once on the machine, regardless of how many times they are used (see Apple:What Are Frameworks) . The benefit here is performance and it is for both the code and the resources in many cases.
Due to the recent move to randomize framework locations,and Apple's comments in the release notes that "Mountain Lion randomly relocates the kernel, kexts, and system frameworks at system boot," it certainly appears they're still sharing these resources, and thus still gaining from this benefit.
For embedded frameworks, the situation is a lot more tedious, and Apple has moved through a variety of methods over the years to make it easier to find frameworks wherever they may be. Due, again, to the shared nature, it would make sense for Applications which share common library requirements to share them on the machine, both for purposes of efficiency, and to make sure they're at the same version if they're sharing data. So, for example, if you have two separate apps that use the same framework to work with shared data, you might put the shared framework in /Library/Frameworks and have both apps explicitly look for that, making sure that some other (possibly older) version of the framework, that has been loaded by another App, is not used instead.
In the end, there's a lot of flexibility for the Framework producer and consumer the way that it currently works. It means that the developer can decide to share a framework, include a private copy of the framework, or even do both, depending upon whether the framework exists on the machine or not. However, the price for that flexibility is the complexity that we have today.
Another example of a reason you might not want to use #rpath specifically is for tightly-linked embedded frameworks (yes, people embed frameworks within other frameworks). In these cases, you don't know where the first framework is loaded, but you want to put the embedded framework inside of it, so that they stay together. In this case #loader_path is relative to the code that is loading it, so that your plug-in's framework can find its resources correctly.
In answer to your specific example about somebody setting the Dynamic Library Install Name
to a "random" location. In this case, you'd have to know that location. There might be many reasons for somebody doing this, such as wanting to discourage reuse by other programs, or because there are large resources within the framework that should only be installed in a known shared location.
I'm fairly new to programming and wanted to start programming more efficiently. Try as I may I often find myself straying from the MVC model.
I was wondering are there any tips or methods in keeping your code organized when coding in xcode objc? To be more specific (I know you guys like that :) I want to
Be able to write libraries or self-containing code that can bring from one project to another
Share my code with others as open sourced projects
Prevent myself from writing messy code that does not follow proper structure
Use a high warning level. Build cleanly.
Remove all static analyzer issues.
Write some unit tests.
Keep the public interfaces small.
Specify your library's dependencies (e.g. minimum SDK versions and dependent libraries).
Compile against multiple/supported OS versions regularly.
Learn to create and manage static library targets. This is all you should need to support and reuse the library in another project (unless you drag external resources into the picture, which becomes a pain).
No global state (e.g. singletons, global variables).
Be precise about support in multithreaded contexts (more commonly, that concurrency shall be the client's responsibility).
Document your public interface (maybe your private one too…).
Define a precise and uniform error model.
You can never have enough error detection.
Set very high standards -- Build them for reuse as reference implementations.
Determine the granularity of the libraries early on. These should be very small and focused.
Consider using C or C++ implementations for your backend/core libraries (that stuff can be stripped).
Do establish and specify any prefixes for your library's objc classes and categories. Use good prefixes too.
Minimize visible dependencies (e.g. don't #import tons of frameworks which could be hidden).
Be sure it compiles without the client needing to add additional #imports.
Don't rely on clients putting things in specific places, or that resources will have specific names.
Be very conservative about memory consumption and execution costs.
No leaks.
No zombies.
No slow blocking operations on the main thread.
Don't publish something until it's been well tested, and has been stable for some time. Bugs break clients' code, then they are less likely to reuse your library if it keeps breaking their program.
Study, use, and learn from good libraries.
Ask somebody (ideally, who's more experienced than you) to review your code.
Do use/exercise the libraries wherever appropriate in your projects.
Fix bugs before adding features.
Don't let that scare you -- it can be really fun, and you can learn a lot in the process.
There are a number of ways you can reuse code:
Store the code in a common directory and include that directory in your projects. Simple, but can have versioning issues.
Create a separate project which builds a static iOS library and then create a framework. More complex to setup because it involves scripting to build the framework directory structure. But easy to use in other projects and can handle versioning and device/simulator combined libs.
Create a separate project which builds a static iOS library and then include this as a subproject in other projects. Avoids having to build frameworks and the results can be more optimised.
That's the basic 3, there are of course a number of variations on these and how you go about them. A lot of what you decide to do is going to come down to who you are going to do this for. For example I like sub projects for my own code, but for code I want to make available for others, I think frameworks are better. even if they are more work to create. Plus I can then wrap them up with docsets of the api documentation and upload the whole lot as a DMG to github for others to download.
I have two projects which share quite a portion of logic, localizations, properties and even views (Logindialog, Popovers etc.). I now want to put the intersecting set into a new project, which should be used as some sort of common library.
I want to keep the common project as a git submodule in my other projects:
Project A
- Classes
- Resources
- CommonLibrary (git submodule)
Project B
- Classes
- Resources
- SomeBSpecificFolder
- CommonLibrary (git submodule)
The CommonLibrary would now probably also be it's own Xcode project. I am not sure now how I should tackle this problem. I know of the following options:
Use a library (.a-file and .h file)
TestFlight e.g. does it like this. I quite like the fact that I can just compile against a binary and don't "see" the source. So just a clean API for doing things.
Include the whole project (Project dependency)
Three20 does it like this and I find it quite annoying to have some 6 subprojects in my project. However in my case it would only be one project, so this might be an option too.
Just have loose source files without a project inside the CommonLibrary folder and manually add them to both of the projects. The project would then compile the sources along with any project-specific sources. This looks a big like a workaround to me and I guess I would prefer to somehow bundle the common sources. Also if there are new files, I always have to add them to the other projects.
Can you guys give me some advice and tell me if there is another option or what you think are the advantages and disadvantages about these approaches?
Thanks a lot for your help!
From a clean, non-application specific perspective, you should be looking to create a library/ framework. This provides:
the reusability you want
without extending build time of dependent projects,
while maintaining consistency of the code base (maintainability),
keeping your API consistent across using projects and
managing dependencies between layers
In terms of Xcode, if I remember correctly from my OpenStep days, you should be looking to create a new Framework project which will provide the relevant makefiles for that type of project. A cursory surf produced:
http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Tasks/CreatingFrameworks.html
and the slightly more friendly:
http://atastypixel.com/blog/creating-applications-in-xcode-using-frameworks/
Furthermore, you might actually want to layer your frameworks to further improve reusability. That is, don't just create one framework, create one per tier: put common code in a Foundation framework, UI/ AppKit-based classes in a UI framework, etc. This way, your frameworks are relevant to whatever tier your using classes and projects live.
For instance, if you have a category on some foundation class, put it in a common/ foundation framework that can be reused by any other common/ foundation classes and projects you build. If you were to put it in a UI-tier framework with UI libraries and dependencies then it couldn't be reused by your foundation level projects (as these can't have UI-level dependencies).
Hope this helps...
I found a project called RestKit on github which seems to be a good example for a third-party framework, which can be included in an existing project.
The readme and the wiki describe nicely which steps need to be done in order to include the project. I guess this is a good starting point for someone who want to create a framework himself.