Sharing classes between projects in xcode/objective-c
I've got a client<=>server app I'm building for Mac OS X, using Objective-c/Cocoa and xCode. I've created a different project for both the apps I have, and I'm wondering the best way to share classes between them. There are several classes I've made that would be useful to both. This far I've been copying th开发者_如何转开发em around, but I feel like this isn't the best solution.
How do I share classes effectively? Should I redo it as 1 project and just have two build targets? How do I do this?
Any other info?
Thanks.
If you have two or more products that are going to share a good amount of common code, like a suite of products, you might want to consider creating just a single xcode project, and then add a different target for each product that will be built from both shared and product-specific code. With a lot of shared code, a client/server pair of products would possibly be great candidates for going this way.
Boiled-down, the basic deal is that for each target in your xcode project that you want to build, you specify which files should be used to build it: source files, art, xibs, and so on. This way, for example, you can setup your client product to be built using files A,B,C,D,E,F, and your server product to be built using files A,F,X,Y,Z.
I really like having every related product living under a single xcode project "roof", because you wont have to jump around xcode projects, and it really simplifies SCM management for the shared files.
Here's a link to Apple's docs on this: https://developer.apple.com/library/mac/#featuredarticles/XcodeConcepts/Concept-Targets.html
Update: there's a little bit of extra hassle involved when it comes to configuring target-specific header files in xcode (it's always something...right?!); for example, use "myHeaderA.h" for this target and "myHeaderB.h" for that target. Here's a great post that shares how to do it: controlling which project header file Xcode will include. Caution: after you set things up this way, xcode no longer knows any paths to search for any of your target header files, so you have to set them up manually. To do this, right-click Get Info on your target, select Build category, then add your paths via the "Header Search Paths" setting. The paths are searched in the order that you enter them.
A very good way to do it is to put the shared code into SCM system and include it into each project you want it in. This way every project can share the code, you can edit it anywhere and just check the changes back into source control when you're feeling good about it — and then all the other projects benefit from your work.
This has big advantages over other ways of doing it IMO:
vs. frameworks: Packaging code into a framework is pretty annoying, and bundle-private frameworks take an unreasonably long time to load — especially just to get a few classes into your app. Wil Shipley of Omni Group (at the time) once found that the frameworks the company included in all their apps were adding several seconds to the start time of each app. Packaging private classes in a framework can also encourage more coupling than is strictly necessary — it's really tempting just to make One True Framework where all your shared classes reside, so you start assuming this code will always live together. and it becomes inseparable. Basically, frameworks are a hammer and this problem is a screw.
vs. just including files: Hopefully you'll put your app into an SCM at some point anyway, and simply including the files in-place creates a problem because they'll be missing from SCM. Copying the files into each project introduces the opposite problem — each project will include its own version of the files and you'll have to manually propagate any useful changes.
The best way is to create a separate framework containing the shared classes. This can be compiled up once and linked into both application projects.
See Apple's doc on what are Frameworks.
The fastest solution is to add only references of the .h and .m files to one of the projects. Just uncheck the "copy"-checkbox in the "add existing files"-dialog in xcode. Keep in mind the you might also need to copy the referenced files if you move/share your project.
I had a similar issue, and the accepted answer above may cause issues for a newbie.
It will be fine the if the two projects communicate by some protocol e.g. TCP/IP, or if they don't communicate. If however one project is a bundle (e.g. a plugin) which needs to access the same classes as an application (whilst being run in the same process) you will get issues with linking or runtime warnings/errors about having classes with the same name. The simplest way to solve this problem is to use a framework. With a framework you can set it up so all three targets are in the same project, or you can even include the framework in separate projects.
I had a project with an app and a bundle plugin, here are the steps I followed in Xcode 6:
- Create a framework, copy all the shared code over.
- In the main header of the framework, include the headers of all the shared code.
- Build the framework to test it builds (e.g. select the scheme of the framework and click play)
- Go to the Build Phases section of both the Application and the Plugin Bundle and add the new framework to ‘target dependencies’ and ‘Link binary with libraries’
- To include the frameworks stuff in code in the app and bundle, just use the main header, and use <> rather than “" e.g if your framework was called Foo use #import
Changes to the framework will be compiled automatically when you run the main app, so you can in effect ignore the fact they are different targets.
I found a nice article on this topic here: http://www.clintharris.net/2009/iphone-app-shared-libraries/ This answers my question which is specifically about multiple iPhone apps sharing code. It doesn't mention frameworks (above) so I can't say if their suggestion (xcode project references) compares favorably to the frameworks solution.
精彩评论