Delegate Protocol conformance, Delegate methods, and @available/#available

Using Xcode 7 beta / iOS 9 beta. I have a UIViewController subclass that implements the UIPopoverPresentationControllerDelegate protocol. The deployment target is set to iOS 7.1. If I do this:

    //MARK: - UIPopoverPresentationController delegate methods
    func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
     // my code
    }

I get the error "UIPopoverPresentationController is only available on iOS 8.0 or newer".

If I use the fix-it suggestion to wrap with @available:

    @available(iOS 8.0, *)
    func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
        // my code
    }

I get the error "Protocol 'UIPopoverPresentationControllerDelegate' requres 'popoverPresentationControllerDidDismissPopover' to be available on iOS 7.1.0 and newer".


How can I indicate that my view controller implements this delegate protocol and define the method if I need the deployment target to be iOS 7.1 (obviously, I provide an alternative way to show my popover in iOS 7.1)?


BTW the second error message is misleading at best, since the delegate protocol, and therefore the specifiid method, are not even available on iOS 7.1.

This should work:


(misunderstood question, see below)

No, that results in an "Expected declaration" error on the "if #available..." statement.

Weird... I just copied and pasted that into one of my projects and it worked. Perhaps try deleting your derived data? I see odd errors pop up from time to time with the Swift compiler and that will sometimes take care of it.

Already tried clean / clean build folder / delete derived data. I am trying to do it inside a class that is a subclass of UIViewController.

class DetailsViewController: UIViewController, UIPopoverPresentationControllerDelegate {
    // other stuff
   // if #available... here gives "Expected declaration" error
   // @available... here gives error about method needs to be available on iOS 7.1.0 and newer
    func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
       // function code
    }
   // other stuff
}


Also tried adding delegate protocol conformance and method definition in an extension (in a separate source file), with the @available(...) statement before the extension definition, and got same error about method needs to be available in iOS 7.1.0 and newer.

Ah, ok, I misunderstood what you were trying to do. My apologies.


Played around in Xcode again and it seems that the only way to get it to compile is to add the @available attribute to the view controller itself:


@available(iOS 8.0, *)
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate


which is probably not what you want.


Perhaps have 2 classes, one for 7 and one for 8 (marked like above) that are owned by your view controller that act as the popover handler and instantiated at load using #available?

Thanks, I was just thinking it might come down to that also. I posted on the Swift forum (https://forums.developer.apple.com/thread/6429) in case there are some Swift gurus over there that aren't watching here. I'll see if there are any more suggestions. Meanwhile, I created a bug # 21490416.

I'm not sure if it can be done in Swift, but in Objective c you could use a pair of macros to handle it.

Have one that tests the iOS version and defines a second macro according to the results.

Then use the resulting macro to code the protocol text.

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000

#define protocol <text to signal protocol is implemented>

#else

#define protocol <comment or other benign code>

#endif

The edit isn't working for me at the moment...

I realized after I posted that this is using the target version and won't change at runtime.

Delegate Protocol conformance, Delegate methods, and &#64;available/#available
 
 
Q