2017-04-17 23 views
0

运行的Xcode 8与SWIFT 3如何将设备令牌从AppDelegate.swift传递到ViewController.swift?

下面是我的ViewController文件

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) 
    } 

} 

下面是我的AppDelegate文件

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!) 
    } 

} 

下面是我的调试区域信息

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

它好像我无法从AppD获取设备标记字符串elegate.swift。 我怎样才能得到它?

或者我可以在didFinishLaunchingWithOptions中获得设备令牌吗?

+0

为什么不你刚刚保存设备令牌串到你的userdefaults? –

+0

竞态条件问题,我想 – iDhaval

+0

你试图获得设备令牌之前,它分配给应用程序委托中的deviceTokenString。 – iDhaval

回答

3

didRegisterForRemoteNotificationsWithDeviceToken在后的viewController的viewDidLoad总是执行,这就是为什么字符串为空的原因。

为了解决你可以做

  • AppDelegate声明弱财产的时机问题。

    weak var viewController : ViewController? 
    
  • ViewController>viewDidLoad设置属性。你不需要guardAppDelegate。如果它不在那里,应用程序不会启动。

    override func viewDidLoad() { 
        print("inside viewDidLoad ") 
        super.viewDidLoad() 
        let appDelegate = UIApplication.shared.delegate as! AppDelegate 
        appDelegate.viewController = self 
    } 
    
  • ViewController把代码加载web请求是一个额外的方法。

    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) 
    } 
    
  • AppDelegate>didRegisterForRemoteNotificationsWithDeviceToken呼叫的方法。

    viewController?.loadRequest(for: deviceTokenString!) 
    
+0

很好解释。但是我有一个疑问,___ if'applicationDidFinishLaunching'总是在viewController___的'viewDidLoad'之后执行,那么为什么控制台会打印这个命令:__YES。,在viewDidLoad__里面?相反,它应该是__inside viewDidLoad,YES .__!对?? – nayem

+0

我不好,我更新了答案。 – vadian

+0

现在,这是有道理的 – nayem