0

My project has an Objective-C class MockupModel that provides mockup information to an iOS Xcode project to help with creating screen shots for the App store.

The project has two targets. The mockup target includes MockupModel.m.

I want the main target (for the actual App) to not include MockupModel.m so that there is no chance of it accidentally being linked in to the shipping App.

However, when I exclude the MockupModel.m from the project using the file's attribute inspector, reasonably enough, the project fails to link. I get an error complaining that the functions of MockupModel are missing.

Is there some way that I can declare MockupModel as optional so that the linker doesn't worry if it is not implemented? At run time my code will check to see if it's available with NSClassFromString(@"MockupModel"), or with [MockupModel class].

Cœur
  • 32,421
  • 21
  • 173
  • 232
Benjohn
  • 12,147
  • 8
  • 58
  • 110
  • Seems like I might be looking for `__attribute((weak_link))__` or `WEAK_LINK_ATTRIBUTE`, but I'm not sure how to declare that on a class, or even if I can use it for a single class? It seems to be a library thing? – Benjohn Oct 09 '14 at 14:01

1 Answers1

1

In your non-main target, add a user-defined preprocessor directive. You could call it USE_MOCKUP_MODEL. Remove MockupModel.h and MockupModel.m from your main target's file list and surround any source that references MockupModel (or the imports) with:

#ifdef USE_MOCKUP_MODEL
//source
#endif

Examples:

#ifdef USE_MOCKUP_MODEL
#import "MockupModel.h"
#endif

Model *myModel = nil;
#ifdef USE_MOCKUP_MODEL
myModel = [MockupModel new];
#else
myModel = [RealModel new];
#endif
Ian MacDonald
  • 11,433
  • 1
  • 21
  • 41
  • Hi Ian, thanks. I went with a preprocessor solution like this in the end. I think I'd prefer to do something clever with the linker (if only to learn a bit about the linker), but this gets the job done! I'm voting up your answer, but I'll leave the question open with the hope that someone can provide a linker based solution (or state that this isn't possible of advisable). – Benjohn Oct 12 '14 at 21:11
  • I'm not sure that makes sense. Your linking happens after compilation of your code; the compilation will be referencing symbols that it will expect to exist after linking is complete. There's no straightforward set of operations a linker can follow in order to strip unknown symbols, so it will always choose to error. Source that references symbols that are not intended to be linked should be removed pre-compile (in the preprocessor step). – Ian MacDonald Oct 14 '14 at 13:35
  • It's possible to test if features in iOS are available using approaches such as `if([XXNewFeatureClass class]!=nil) {[XXNewFeatureClass doSomething];} else {//fallback option.}` See [here](http://stackoverflow.com/a/10068079/2547229) for an example. Provided a declared symbol isn't actually used (the responsibility for that is mine on pain of a crash), then whether it's linked in or not just depends on whether a code file exists for it or not. I'm pretty sure this _is_ possible if I put the mock up model in a separate library, but I'd like to not need to do that :-) – I should probably learn! – Benjohn Oct 14 '14 at 13:47
  • More about [weak linking](http://stackoverflow.com/questions/16922013/what-does-it-mean-to-weak-link-a-framework) a framework. More about [developing frameworks](https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/CreatingFrameworks.html) in Xcode. – Benjohn Oct 14 '14 at 13:51
  • You can create a second target and remove the file from it. Open the File Inspector (`View -> Utilities -> Show File Inspector`) and you'll see a Target Membership box -- just uncheck the projects you don't want it to link within. – Ian MacDonald Oct 14 '14 at 13:55
  • :-) I think this is what I describe in the question? The problem is that (without preprocessor workarounds) the linker complains that the symbols are missing for the project where they are missing. Which, of course, they are. But I want it to not worry about _these_ missing symbols. – Benjohn Oct 14 '14 at 14:02
  • Why not just duplicate the `@implementation`, but remove all functionality? It would be safer and less likely to experience run-time crashes. – Ian MacDonald Oct 14 '14 at 14:12