0

how to use a function from view controller in appdelegate? in swift 4.

let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as! ViewController

viewController.setapnsText(token: deviceTokenString)
public func setapnsText(token: String) -> Void {
            apnsToken.text=token
}

i tried and it does not work.

Hamish
  • 78,605
  • 19
  • 187
  • 280
  • 1
    could your clarify what result you want to achieve? – Taras Chernyshenko Aug 02 '17 at 14:27
  • 1
    Don't repost questions. I marked your [previous question](https://stackoverflow.com/questions/45459888/how-to-present-apns-token-in-view-controller) as duplicate. In the linked question there are a lot of ways to get the device token as string and this works probably even in Swift 4. Apart from that it's not clear what you are going to accomplish. – vadian Aug 02 '17 at 14:28
  • You can store access token in User defaults. – Jaydeep Vora Aug 02 '17 at 14:29
  • I want that the string of the apns token will appear on the screen in a label. – Itay Geffen Aug 02 '17 at 14:30
  • In `AppDelegate` get the token, convert it to string and save it in a stored property. `AppDelegate` is available from everywhere. In any view controller you can get the string directly from the property of `AppDelegate` and display it. – vadian Aug 02 '17 at 14:37
  • I don't want to get the device token as a string. I want to determine a label value to the of the device token. I posted the parts of the code that I have a problem with it. In my question, I wanted a reply that will explain to me what is wrong with the code. – Itay Geffen Aug 02 '17 at 14:41
  • But how do I adjust the timing? I tried to debug it and it first executed the view controller code and it didn't determine the device token yet from the AppDelegate. – Itay Geffen Aug 02 '17 at 14:48

1 Answers1

1

You can only recieve the device token on each launch if and WHEN the user has/grants your app permission for Push Notifications. Also, This can Usually and most easily be captured in AppDelegate.

So in my example here, i save to both UserDefaults(less recommended), AND core data (more recommended, since you can take advantage of local encryption if you enable that for your app).

You request authorization like so, for an App which is meant to work on iOS 10 + and which asks for Push notifications AT Launch..:

class AppDelegate: UIResponder, UIApplicationDelegate {


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        notificationHandler(application)
        return true

    }


    func notificationHandler(_ application: UIApplication) {
        if #available(iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            center.getNotificationSettings(){ (settings) in
                switch settings.authorizationStatus {
                case .authorized:
                    print("Authorized Push Notifications by User")
                    self.registerPushNotifications()
                case .denied:
                    print("show user a view explaining why it's better to enable")
                    self.registerPushNotifications()
                case .notDetermined:
                    self.requestPushNotifications(center: center, { (granted) in
                        if granted {
                            self.registerPushNotifications()
                            return
                        }
                        print("User did not grant Remote Notifications Authorizations")
                    })
                }
            }
        } else {
            print("App does not meet minimum OS Requirements")
            return
        }
    }

    fileprivate func requestPushNotifications(center: UNUserNotificationCenter,_ result: @escaping(Bool)->Void) {
        center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
            if error != nil {
                print("Could not request Authorization for Notifications - Yet is undetermined")
            } else {
                result(granted)
            }
        }
    }

    func registerPushNotifications() {
           if #available(iOS 10.0, *) {

               UIApplication.shared.registerForRemoteNotifications()

            } else {
                print("App does not meet base OS requirements")
            }
     }

     func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
            let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
            UserDefaults.standard.set(deviceTokenString, forKey: "devicetoken")
            coreDataManager.saveDeviceToken(deviceTokenString)
      }

}

Eventually, if you want to only request this at other moments in your app, you can extend NSObject, since it's the superclass of both AppDelegate and UIViewController (which is the root class of all Controller-type classes anyways.

class AppDelegate: UIResponder, UIApplicationDelegate {


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        notificationHandler(application)
        return true

    }

     func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
            let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
            UserDefaults.standard.set(deviceTokenString, forKey: "devicetoken")
            coreDataManager.saveDeviceToken(deviceTokenString)
      }

}

extension NSObject {

    func notificationHandler(_ application: UIApplication) {
        if #available(iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            center.getNotificationSettings(){ (settings) in
                switch settings.authorizationStatus {
                case .authorized:
                    print("Authorized Push Notifications by User")
                    self.registerPushNotifications()
                case .denied:
                    print("show user a view explaining why it's better to enable")
                    self.registerPushNotifications()
                case .notDetermined:
                    self.requestPushNotifications(center: center, { (granted) in
                        if granted {
                            self.registerPushNotifications()
                            return
                        }
                        print("User did not grant Remote Notifications Authorizations")
                    })
                }
            }
        } else {
            print("App does not meet minimum OS Requirements")
            return
        }
    }

    fileprivate func requestPushNotifications(center: UNUserNotificationCenter,_ result: @escaping(Bool)->Void) {
        center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
            if error != nil {
                print("Could not request Authorization for Notifications - Yet is undetermined")
            } else {
                result(granted)
            }
        }
    }

    func registerPushNotifications() {
        if #available(iOS 10.0, *) {

            UIApplication.shared.registerForRemoteNotifications()

        } else {
            print("App does not meet base OS requirements")
        }
     }

}

You can then call this inside a button's linked method like so:

class SomeController : UIViewController {

   override viewDidLoad() {
      super.viewDidLoad()
   }

   func requestNotificationsAuthorization() {
      notificationHandler(UIApplication.current)
   }

}
jlmurph
  • 1,050
  • 8
  • 17