I've not found anything that addresses my specific name space question as yet.
I am working on some AudioUnit plug-ins featuring Cocoa based GUIs. The plug-ins use a common library of user interface classes (sliders, buttons etc) which are simply added to each Xcode project.
When I recompile and distribute updates it is pretty much guaranteed that at least one user interface class will have been updated since the last release. If the user launches an older plug-in before an updated plug-in then the old Cocoa classes are already loaded into the run time and the plug-in attempts to use the older implementations - often resulting in a failure one way or another.
I know frameworks are the intended solution but the overhead and backwards compatibility issues are not ideal. I prefix all class names where possible but what options do I have to ensure that each plug-in contains unique class names for the shared user interface classes?
Update:
The solution I seem to be arriving at is as follows:
Set a preprocessor compiler flag e.g. OBJC_PREFIX=1.
Create a header file to contain all the class name redefinitions and conditionally include it in the header of each class you want to 'rename' e.g:
#ifdef OBJC_PREFIX
#include "CocoaPrefixHeader.h"
#endif
#interface MySlider : ... etc
Fill the header file (in this case CocoaPrefixHeader) with something like the following:
#define MySlider Prefix_MySlider
#define MyButton Prefix_MyButton
Using ibtool convert all your class names in an existing nib/xib file to the new names e.g:
ibtool --convert MySlider-Prefix_MySlider nibfile.xib --write nibfile2.xib
ibtool --convert MyButton-Prefix_MyButton nibfile2.xib --write nibfile2.xib
This last step converts all class names and outlets etc in the nib file. Once converted you can edit the nib as normal and IB keeps track of the redefined names.
This process is tedious and laborious but it is working for me. Far better to cater for it at the outset.
In your pre-compiled header (.pch) file for each plug-in, you can #define the classes to have different names, e.g.:
#define ClassNameUsedInYourCode ClassNameCompiledInThisProject
#define WidgetButton WahWahPedalPluginWidgetButton
As long as you're creating your UI programmatically, this will ensure that the class names are unique per-plugin. Unfortunately this won't work if you have class names baked into nib files.
In that case, you'd probably need to have some sort of pre-processing script that runs before compilation and replaces any instances of the shared class names with the project-specific class names in all files in the project, including the .xib files. This could get pretty messy but I can't see too many options.
I had a similar issue. I needed to have more than one version of the same bundle running in the same application space at the same time (I can't even remember why). It was not easy, I discussed my problems and options on the Objective-C mailing list. In the end, I modified the build-environment to:
Scan every header for classes declared with #interface.
Create a new header filled with only preprocessor macros that redefine classnames from MyClass to MyClass_v1_00 (or whatever version was defined by the Info.plist file). This header was called ClassRenamer.h.
As an intermediate build step, parse all xib XML files and replace references of MyClass to MyClass_v1_00. This doesn't modify the original xib files, which is handy.
Modify the command-line build flags to include ClassRenamer.h for all .m files.
Surprisingly, everything works perfectly, both at runtime and even in the debugger. If I put a breakpoint on a particular line, it breaks on any version of the class that is loaded, and Xcode even shows the class's name as MyClass_v1_00. The biggest concern is code that looks up classes by name, i.e. using NSClassFromString.
Whilst the solution I arrived at in the updated part of the question works as the final step in a project I can't recommend it for anything where your classes are in a state of flux. I was unable to add additional outlets to classes and have them show up in IB, for example.
In the end I just duplicated my classes and added unique name prefixes for different projects. Using ibtool --convert to update the xib file made this process a lot faster.
Once things settle down maybe a framework will be a better idea.
Related
I've noticed that while editing header files, XCode does not auto-suggest header files to import or classes from imported files unless the file you are editing is itself imported by some file that is included in the target.
I kind of get the reasons for this, but it's super lame. I'm very happy to take the trade off of disappointment at compile time (oops! that wasn't a class that I could import) for the benefit of saving a ton of time while writing headers.
By the way I'm aware that I can use forward class and protocol declarations but this is not helpful because I often need to use something whose name I've not committed to memory. Once I know the thing to forward-declare, then I will!
Is there any way to get XCode to be more liberal about this?
Edit: with pictures
Here's what I see in a header file included by an implementation file that is added to a target when I type the letters "#i":
Now I comment out the include of the header I was editing
Now here's what I get - but autocomplete still works
When I make a new protocol, of course it is not imported by some implementation file (because it is new and it is not a class, so there is no associated implementation file already created).
So autocomplete of imports (and classes) doesn't work... until I import it from an implementation
And now autocomplete works
I have two frameworks in my Xcode project that both define a class with the same name (B.framework and C.framework both have a class named MyClass), resulting in a couple warnings like so:
Duplicate symbol _OBJC_METACLASS_$_MyClass originally in B.framework/B(MyClass.o) now lazily loaded from C.framework/C(MyClass.o)
Duplicate symbol _OBJC_CLASS_$_MyClass originally in B.framework/B(MyClass.o) now lazily loaded from C.framework/C(MyClass.o)
Then at run time only one of the implementations is loaded, and trying to use the other one will result in a "unrecognized selector sent to instance" because they are totally different classes (even though they have the same name).
I use one of the MyClass implementations directly in my code, but the other framework only uses its MyClass internally and I have no idea why its even exported (its not even mentioned in the frameworks header files, i used nm to view the symbols).
How can I make both frameworks work?
There's no such thing as "exported" classes in Obj-C. Or rather, there's no such thing as "non-exported" classes. This problem is precisely why the use of 2- or 3-letter prefixes on classes is strongly recommended for all Obj-C code. Your only solution (besides not using these frameworks) is to edit one (or both) of the frameworks to change the class name, or if you don't have access to the source, then you need to contact the vendor and ask them to make that change.
Using a static function, I can limit the linkage of my function to the file at hand and that is perfect in many cases. But I have a class that is unwieldy as one file, but breaking it up is made more frustrating because there are functions that I would like to keep 'private' but are needed throughout.
One part of the answer must be counter-questions, such as:
Why is your class so big that it must be split up?
Are you sure your class is so big that it must be split up? (How big is 'big'?)
Are you sure you have your class properly abstracted?
Can you make the common functions into a new class that can be used by the main class you are working with? That will hide the functions behind a class interface barrier.
On the whole, if you can avoid it, do not split the class file up arbitrarily because of size constraints; keep together that which belongs together.
A Gruesome Possibility
Assuming that a split is necessary and an orthodox split (into various classes that work together) is not possible, the question becomes: how gruesome will you accept your code being? (It's already a bit gruesome since there's an awful lot of functionality in a single file; can you stand it becoming more gruesome?)
Assume your class is in 4 (or more) files.
class.h
class.c
class1.c
class2.c
The header, class.h, is orthodox - self-contained and idempotent. It is used by the outside world (meaning outside this collection of source code) to access the facilities provided by the class.
The files class1.c and class2.c contain implementations of the functions in the class. They could be given a separate, distinctive file suffix - there might be some advantages to doing so. The files are not designed to be compiled standalone; they are strictly a convenience that splits the source up because the class got too big.
The file class.c is what you compile. It contains:
#include "class.h"
Other definitions needed by the class internals.
#include "class1.c"
#include "class2.c"
Thus, although the source is split up, you actually compile a single file, class.c.
In your makefile or equivalent, you specify that class.o depends on the header and all three source files; if any of those changes, then you need to recompile the whole lot. One advantage of changing the suffix of the implementation files (class1.c and class2.c) is that they will not compile separately because the suffix is not recognized by the C (Objective-C) compiler. One downside of changing the suffix is that your syntax-aware editor won't be aware of the correct syntax highlighting for the separate files unless you tell it the file type. If you use an IDE, it may also be less than amused at this trickery.
If you work on a machine where the size of the source means it cannot all be compiled at once like this, then you are snookered. This technique does not help at all; you have to split the files up and compile them separately. In that case, really look hard at whether you can split the code cleanly into several classes which can be managed in an orthodox way.
By request, my comment on the OP as an answer:
There's no language support for this that I'm aware of... You could put all the support functions in a separate c file and only #import its header from the class implementation files? If they don't have to be C functions (for passing as callbacks to C APIs, for example) I'd reimplement them as methods on the class and declare the private interface in a separate header—each implementation file would then #import both the "public" and "private" header.
Prefix their names with output of a cryptographic RNG. Now you don't have to worry about unintentional name collisions. Problem solved. You can hide the renaming in preprocessor macros if you really like.
My XCode project has grown somewhat, and I know that there are class files in there which are no longer being used. Is there an easy way to find all of these and remove them?
If the class files just sit in your project without being part of a target, just click on the project itself in the tree view, so you see all files in the table. Make sure you see the "Target" column in the table view, iterate through your targets and find the files that don't have a check anywhere -> they are no longer compiled.
But if you still compile the classes and they are no longer used, that case is a bit more difficult. Check out this project
http://www.karppinen.fi/analysistool/#dependency-graphs
You could create a dependency graph and try to find orphaned classes that way.
Edit: Link went dead, but there still seem to be projects of Objective-C dependency graphs around, for example https://github.com/nst/objc_dep
if they are C or C++ symbols, then you can just let the linker do the work for you.
if you're looking to remove objc symbols, then try to refactor the class name (e.g. to rename the class), and preview the dependencies that it turns up. if you reference classes/selectors/etc. by strings then... it may not be so effective. unfortunately, you often have to also test manually, to verify that removing a class does not break anything. remember that resources (like xibs) may reference/load objc classes as well.
This is a tricky question due to how dynamic objective-c is as you can never guarantee that a class is not going to be used.
Consider if you generate a class name and a selector at run time and then look up that class, instantiate that class and then call a method on that newly created object using that newly created selector. No where in your code do you explicitly name and instantiate that object but you are able to use it anyways. You could get that class name and selector name from anywhere outside of your code, even from some data from a server some where. How would you ever know which class is not going to be used? Because of this there are no tools that are able to perform what you are requesting.
Searching the project with the class name might be an option, thought it may not be the best solution. Specially it might be time consuming when you have many classes.
I have an idea on how to do this, but I want to make sure I do it right....
I have five data classes. When I use one I typically use all of them (but not always).
Each class has a separate header file. I am getting sick of linking in each header file separately.
What is the best way resolve this issue?
Create a new header file called "DataFiles.h". Inside that, have your five #import statements. Then whenever you need the file classes, just #import "DataFiles.h".
Beware of circular dependencies.
(This is how Cocoa, Foundation, UIKit, CoreData, etc all behave. Notice that you just #import <Cocoa/Cocoa.h>, which imports everything else. Open up Cocoa.h and take a look)