xcodeimportsettings

Need help understanding Xcode *.pch files


I'm working on a 3rd party UIKit replacement for iOS. I have it building as a framework using a seriously helpful project from GitHub. (Not mine, but if you have interest, it's here.

I'm trying to use my library in other projects I'm writing. Like I said, it's basically a drop-in replacement for much of UIKit, so I decided to import the framework in my project's *.pch file instead of everywhere I might wish to use a button, action sheet, alert view, etc...

When I DON'T have an #import directive in a header file and declare a property of type MBMButton, the compiler gives me an error of "Unknown type name 'MBMButton'; did you mean 'UIButton'?" Oddly enough, the code will still run (even though this is an error, not a warning). Adding @class MBMButton or #import <MBMUIKit/MBMUIKit.h> resolves this compiler complaint.

When I DON'T have an #import directive in an implementation file (or its header) and call a method that exists in MBMUIButton but NOT in UIButton, I get a compiler error of "No visible @interface for 'UIButton' declares the selector...". As before, the code will actually run, since it's a valid call.

Now, I've done some digging, and I've changed my project's settings. Where I didn't have any value in the GCC_PREFIX_HEADER, I added the file name. Noting the Quick Help description by Apple, I tried both "ProjectName-Prefix.pch" and "./ProjectName-Prefix.pch". Neither seemed to resolve the problem. I eventually figured out that the Target-level settings override the Project-level settings, and that the Target-level settings already specified "ProjectName/ProjectName-Prefix.pch". So that was a dead end. (Nice to learn exactly what the relative path settings are, though!)

I'm OK with not using the *.pch file. It's only a convenience, and I can definitely use appropriate @class and #import directives. What's bugging me is not understanding the issue. How should one use the *.pch file?


Solution

  • The prefix header file is automatically included in every .m file in your project but not in any .h files.

    Therefore, any references to classes will require the header to be included or a forward declaration:

    @class MyClass;
    

    However for @protocols you'll need the full header, a forward declaration won't work:

    @protocol MyProtocol; //this won't work
    
    @interface MyController : UIViewController <MyProtocol>
    
    …
    @end