1

We have an application supporting iOS 9+, that is being developed in Swift 3 and Xcode 8.2.x. iOS 10 introduced a new method for registering for push notifications, described well in this post. Since iOS 9 doesn't know about the User Notifications framework, we want to use the iOS 9 method when the device is iOS 9, and use the UserNotifications.framework on iOS 10. In Objective C, we would accomplish this via conditional compilation (e.g. #ifdef statements).

In Swift 3, there is some facility for conditional compilation #available and #if. We try to wrap the branches of notification registration code in either of these directives, and the app will not compile.compilation error #available generates similar results

This is the case when targeting generic/real devices. The app will compile against simulators.

Community
  • 1
  • 1
gudatcomputers
  • 2,822
  • 2
  • 20
  • 27
  • This is interesting... Not able to reproduce this compile issue. Try to clean project and delete derived data if you haven't already? – Pratik Patel Mar 03 '17 at 20:31
  • I'll give that a shot on Monday. Are you building for "Generic iOS Device" or an actual device? That's where the issue occurs. As I mentioned it compiles against simulators. – gudatcomputers Mar 04 '17 at 06:02
  • Is conditional compilation really what you want? You have separate builds for iOS 9 and iOS 10? – zpasternack Mar 04 '17 at 20:46
  • Also note, `#available` isn't conditional compilation, it's a runtime check. – zpasternack Mar 04 '17 at 20:46
  • Yeah understood on #available. Conditional compilation was the closest thing I could think of. We want the new framework on iOS 10 and old framework on iOS 9. If you try to build on an iOS 10 device (or generic), it will not build because it doesn't know about UIUserNotificationSettings. There was a similar check we did when the IOS 7 method for registering was introduced. We did something similar in Objective C and didn't have a problem. We didn't have the problem because 7 still knew about the 6 method. It doesn't seem like 10, under these circumstances, isn't recognizing the 9 way. – gudatcomputers Mar 04 '17 at 20:52

1 Answers1

1

Based on your comments above, you want a runtime check, not conditional compilation, and #available is precisely that.

This works fine for me:

if #available(iOS 10.0, *) {
    UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) {
        (granted, error) in
    }
}
else {
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
}

UIUserNotificationSettings is deprecated in iOS 10, but it's actually still there. Apple doesn't typically remove APIs until they've been deprecated for a very long time.

I suspect you have some other kind of build issue. Off the top of my head: do you have Base SDK and Deployment Target set correctly?

zpasternack
  • 17,838
  • 2
  • 63
  • 81
  • Yeah deployment target is set to 9 for sure. I'll double check base SDK. Like I said though, that available check works for sims but won't compile on Generic device or a physical device attached to the Mac. Are you seeing success in those two scenarios? – gudatcomputers Mar 17 '17 at 04:15
  • Yep, works with both Generic iOS Device, and my trusty ole iPhone 5s. – zpasternack Mar 17 '17 at 04:31
  • I think I've figured it out. @zpasternack This project is using Swift 3. It won't let me change the base SDK because Swift 3 is only in the new SDK I suppose. – gudatcomputers Apr 02 '17 at 17:10