9

I'm using Xcode 11 on the GM build of Catalina (10.15). I'm working on building my iOS app for Mac Catalyst. My iOS app has a deployment target of iOS 11.

I have a simple line in a view controller such as:

self.modalInPopover = YES;

Compiles clean in iOS. When I switch to the "My Mac" destination, I get a deprecation warning:

'modalInPopover' is deprecated: first deprecated in macCatalyst 13.0

OK, fine. I can switch to the new method added in iOS 13:

if (@available(iOS 13.0, *)) {
    self.modalInPresentation = YES;
} else {
    self.modalInPopover = YES;
}

That should fix it but I still get the same deprecation warning on the use of modalInPopover in the else block.

What's odd is that the corresponding Swift code does not give any warnings. Only the Objective-C code continues to give the warning.

if #available(iOS 13, *) {
    self.isModalInPresentation = true
} else {
    self.isModalInPopover = true
}

I even tried updating the @available to:

if (@available(iOS 13.0, macCatalyst 13.0, *)) {

but that didn't change anything.

The following disaster solves the problem but it shouldn't be needed:

#if TARGET_OS_MACCATALYST
    self.modalInPresentation = YES;
#else
    if (@available(iOS 13.0, *)) {
        self.modalInPresentation = YES;
    } else {
        self.modalInPopover = YES;
    }
#endif

Am I missing something or is this an Xcode bug? How can I eliminate the deprecation warning in Objective-C without duplicating code using #if TARGET_OS_MACCATALYST which isn't need in Swift.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • You don't need `self.modalInPresentation = YES;` for iOS if your's deployment target iOS11 – Cy-4AH Oct 07 '19 at 11:36
  • I don't know why it's disaster: project that targets both platforms should have target checks everywhere. – Cy-4AH Oct 07 '19 at 11:37
  • @Cy-4AH "Disaster" is a little strong but it's a problem because it's duplicating code. And again, why is it only an issue with Objective-C and not Swift? – rmaddy Oct 07 '19 at 15:14

2 Answers2

1

My iOS app has a deployment target of iOS 11.

That’s why. To see the deprecation warning in Swift you would need to say isModalInPopover not in an available clause with a deployment target of iOS 13.

For the Catalyst build, you're not backward compatible (there is no backward) so it's as if this were an iOS 13 deployment target, and you see the warning.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Think about it this way: it's only a deprecation. If you say something deprecated in iOS 13 but you're in an iOS 11 deployment target, your code is fine for iOS 11 and iOS 12 and it will actually work in iOS 13, so there's no point yanking your chain. But if you switch to an iOS 13 deployment target, all the deprecation warnings for iOS 13 spring to life. My technique is to do exactly that, switch to iOS 13 deployment target temporarily just so I can see if I am accidentally using any deprecated API, then switch back later. – matt Oct 07 '19 at 01:54
  • But my question was based on a test iOS project with mixed Swift and Objective-C code with a deployment target of iOS 12. That project only gives a deprecation warning for the Objective-C code when building for a Mac. Why give a warning only for the Objective-C code and not the Swift code in the same project? – rmaddy Oct 07 '19 at 02:31
  • Because Swift is smarter about availability? I mean, do try what I said and you’ll see that it’s true: the iOS 13 deprecation warnings show up only if the deployment target is iOS 13. This behavior is not new: as I said, I routinely play this game in order to learn of new deprecations. – matt Oct 07 '19 at 02:41
  • Well the ultimate question is how do I compile cleanly, in Objective-C, without having to duplicate code with the `#if TARGET_OS_MACCATALYST`? – rmaddy Oct 07 '19 at 02:52
  • Ok that sounds interesting but that’s not the question you asked. – matt Oct 07 '19 at 02:53
  • Hmm. That's certainly the one I meant but after reviewing what I wrote I suppose I didn't make that goal as clear as I thought. Updated the last paragraph to make that clear. – rmaddy Oct 07 '19 at 03:01
1

You can use this to check whenever you running it on different platforms:

#if targetEnvironment(macCatalyst)
    print("UIKit running on macOS")
#elseif os(watchOS)
    print("Running on watchOS")
#else
    print("Your regular code")
#endif

also it should remove the warning. More details can be found here: https://www.hackingwithswift.com/example-code/catalyst/how-to-detect-your-ios-app-is-running-on-macos-catalyst

Oleg
  • 591
  • 5
  • 14