Dreams
Dreams

Reputation: 8506

How can I pass device token from AppDelegate.swift to ViewController.swift?

Running xcode 8 with swift 3

Below is my ViewController file

class ViewController: UIViewController {

    @IBOutlet weak var testWebview: UIWebView!


    override func viewDidLoad() {
        print("inside viewDidLoad ")
        super.viewDidLoad()

        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        }
        guard let deviceTokenString = appDelegate.deviceTokenString else {
            print("can not get device token string")
            return
        }


        let deviceid = UIDevice.current.identifierForVendor!.uuidString
        print("====== device id =======")
        print(deviceid)

        let testURL = URL(string: "http://www.test.com/user?device=ios&deviceid=" + deviceid + "&devicetoken=" + deviceTokenString)


        let testURLRequest = URLRequest(url: testURL!)
        print("before load request")
        print(testURL!)
        RJWebview.loadRequest(testURLRequest)
    }

}

Below is my AppDelegate file

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var deviceTokenString: String?



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

        let center = UNUserNotificationCenter.current()

        center.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { granted, error in
            if granted {
                print("YES。")
            }
            else {
                print("NO!")
            }
        })

        application.registerForRemoteNotifications()

        return true
    }


    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
        print("==== didRegisterForRemoteNotificationsWithDeviceToken ====")
        print("===== deviceTokenString =====")
        print(deviceTokenString!)
    }

}

Below is my debug area message

YES。
inside viewDidLoad 
can not get device token string
==== didRegisterForRemoteNotificationsWithDeviceToken ====
===== deviceTokenString =====
DF9AB59resrF68532C07ECB00627E4632F08F02975D5C4adsfsd2e810A5EB4

It seems like I can not get device token string from AppDelegate.swift. How can I get that?

or can I get device token in didFinishLaunchingWithOptions ?

Upvotes: 1

Views: 3900

Answers (1)

vadian
vadian

Reputation: 285082

didRegisterForRemoteNotificationsWithDeviceToken is executed always after viewDidLoad of the viewController, that's the reason why the string is empty.

To solve the timing issue you could do

  • In AppDelegate declare a weak property.

    weak var viewController : ViewController? 
    
  • In ViewController > viewDidLoad set the property. You don't need to guard AppDelegate. If it was not there the app wouldn't have launched.

    override func viewDidLoad() {
        print("inside viewDidLoad ")
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.viewController = self
    }
    
  • In ViewController put the code to load the web request is an extra method.

    func loadRequest(for deviceTokenString : String)
    {
        let deviceid = UIDevice.current.identifierForVendor!.uuidString
        print("====== device id =======")
        print(deviceid)
        let testURL = URL(string: "http://www.test.com/user?device=ios&deviceid=" + deviceid + "&devicetoken=" + deviceTokenString
    
        let testURLRequest = URLRequest(url: testURL!)
        print("before load request")
        print(testURL!)
        RJWebview.loadRequest(testURLRequest)
    }
    
  • In AppDelegate > didRegisterForRemoteNotificationsWithDeviceToken call the method.

    viewController?.loadRequest(for: deviceTokenString!)
    

Upvotes: 5

Related Questions