0

To generate local notifications in my library, I need to use either UserNotification or UILocalNotification depending on what my host app uses. (Some customers are still using the deprecated didReceiveLocalNotification: API).

Now when I create my notification, is it possible, at runtime, to determine which system the host app uses and create the appropriate APIs. This means I will need to conditionally import and use the UserNotification header file.

EDIT: Regarding the use of NSClassFromString:

if (NSClassFromString(@"FrameworkClass") == nil) {
   // the framework is not available
} else {
   // the framework is avaiable
}

But I have a lot of UserNotification code to write. I don't think using performSelector: would be very practical.

NSRover
  • 932
  • 1
  • 12
  • 29

3 Answers3

0

What about preprocessor macros?

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
// Only COMPILE this if compiled against BaseSDK iOS10.0 or greater
#import <UserNotifications/UserNotifications.h>
#endif
arturdev
  • 10,884
  • 2
  • 39
  • 67
  • This is a compile time check. This will not work in my case since I have to make the decision at runtime. – NSRover Oct 10 '17 at 03:13
0

This is example Register for remote notifications checking API

In Swift

if #available(iOS 10.0, *) {
  // For iOS 10 display notification (sent via APNS)
  UNUserNotificationCenter.current().delegate = self

  let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
  UNUserNotificationCenter.current().requestAuthorization(
    options: authOptions,
    completionHandler: {_, _ in })
} else {
  let settings: UIUserNotificationSettings =
  UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
  application.registerUserNotificationSettings(settings)
}

application.registerForRemoteNotifications()

In Obj-C

if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
  UIUserNotificationType allNotificationTypes =
  (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
  UIUserNotificationSettings *settings =
  [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
  [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
  // iOS 10 or later
  #if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
  // For iOS 10 display notification (sent via APNS)
  [UNUserNotificationCenter currentNotificationCenter].delegate = self;
  UNAuthorizationOptions authOptions =
      UNAuthorizationOptionAlert
      | UNAuthorizationOptionSound
      | UNAuthorizationOptionBadge;
  [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
      }];
  #endif
}

[[UIApplication sharedApplication] registerForRemoteNotifications];
Joyal Clifford
  • 1,212
  • 11
  • 20
  • UINotifications are deprecated but not discontinued on iOS 10, 11. Its possible that an app might chose to still use UINotifications. – NSRover Oct 10 '17 at 03:16
0

I don't think you can import a framework at runtime in Objective-C.

You can tap into objective c runtime magic and use performSelector: to call selectors/methods without importing a class/framework but you don't necessarily want to use it as there is no compile-time checking on selector names and may result in app crashes if it is not used propertly.

The only way I can think of achieving what you want is to weak-link UserNotifications framework in your library.

On runtime you can check whether your client supports the framework, and if the framework symbols are available, you can run them safely.

Doing it this way, you get the compile time safety of method name checking, and you can write your code in a normal manner but yeah don't forget to check for the availability of the framework before executing any of its symbols.

Puneet Sharma
  • 9,369
  • 1
  • 27
  • 33
  • Yea thats the approach I am going with. However, how do I check wether the host app supports the framework? – NSRover Oct 10 '17 at 06:08
  • @NSRover: You can simply use if( [UserNotifications class]). But make sure you have weakly-linked UserNotifications framework in your library, i.e. made framework linking optional in build phases of your target. – Puneet Sharma Oct 10 '17 at 06:11