Search code examples
iosxcodepreprocessorconditional-compilation

How to use preprocessor checks in header file?


Okay I know there's a lot of posts on this, but I'm still having trouble. Here's the pseudo code for what I'm trying to do:

if(device is running iOS 5 or up)

    @interface RootViewController : UIViewController <UIPageViewControllerDelegate, UIGestureRecognizerDelegate>

    @property (strong, nonatomic) UIPageViewController *pageViewController;

else

    @interface RootViewController : UIViewController <LeavesViewDelegate, UIGestureRecognizerDelegate>

    @property (strong, nonatomic) LeavesViewController *leavesViewController;

endif

Am I right in thinking I need to use pre-processor macro checks since it's in the header file? It's a book app that should use UIPageViewController if it's iOS 5 or up (and therefore has UIPageViewController), otherwise it falls back on Leaves (https://github.com/brow/leaves). I have all the code set up. Just need to know how to tell the compiler which to use. I don't think using any runtime checks would work since I only need the protocol methods for either UIPageViewController or Leaves compiled, not both. And I'd rather not use completely separate source files. I've tried using these checks:

#ifdef kCFCoreFoundationVersionNumber_xxx

#ifdef __IPHONE_xxx

#if __IPHONE_OS_VERSION_MAX_ALLOWED <__IPHONE_xxx

(with various xxx's)

What am I missing here?

EDIT:

I also noticed this in the default .pch:

#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif

which makes me wonder why that same test didn't work in my .h file?


Solution

  • As I mentioned in the comments, you can't do this at compile time.

    But here's an idea for you: It seems that the method names of UIPageViewControllerDelegate and LeavesViewDelegate do not intersect, so you could add the following to your header file:

    -(void) leavesView:(LeavesView*)leavesView willTurnToPageAtIndex:(NSUInteger)pageIndex;
    -(void) leavesView:(LeavesView*)leavesView didTurnToPageAtIndex:(NSUInteger)pageIndex;
    -(void) pageViewController:(UIPageViewController*)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray*)previousViewControllers transitionCompleted:(BOOL)completed;
    -(UIPageViewControllerSpineLocation) pageViewController:(UIPageViewController*)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation;
    

    and not explicitly adopt the delegate protocols in the header file (leave out the delegates inside the < >).

    Whatever classes you're using for these two could be instantiated in your *.m file in a condition along the lines:

    // check for existence of class to determine which controller to instantiate
    if(NSClassFromString(@"UIPageViewController"))
    {
        // do something and set UIPageViewController delegate to "self"
    }
    else
    {
        // do something else and set LeavesViewController delegate to "self"
    }
    

    Lastly, to get this to compile, you will probably need to forward declare all LeavesViewController- and UIPageViewController-related classes where you use them, and possibly utilize weak linking for some frameworks.

    I haven't yet used Apple's UIPageViewController classes and protocols, so I can't provide much more insight than this. Be sure to let us know if you get something hammered out :)