Ios 如何将设备令牌从AppDelegate.swift传递到ViewController.swift?

Ios 如何将设备令牌从AppDelegate.swift传递到ViewController.swift?,ios,swift,xcode,Ios,Swift,Xcode,使用swift 3运行xcode 8 下面是我的ViewController文件 class ViewController: UIViewController { @IBOutlet weak var testWebview: UIWebView! override func viewDidLoad() { print("inside viewDidLoad ") super.viewDidLoad() guard let

使用swift 3运行xcode 8

下面是我的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
似乎我无法从AppDelegate.swift获取设备令牌字符串。 我怎么能得到这个


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

DidRegisterForRemotionTificationswithDeviceToken
总是在viewController的
viewDidLoad
之后执行,这就是字符串为空的原因

要解决时间问题,您可以这样做

  • AppDelegate
    中声明弱属性

    weak var viewController : ViewController? 
    
  • ViewController
    viewDidLoad
    中设置属性。您不需要
    保护
    AppDelegate
    。如果没有它,应用程序就不会启动

    override func viewDidLoad() {
        print("inside viewDidLoad ")
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.viewController = self
    }
    
  • ViewController
    put中,加载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!)
    

始终在viewController的
viewDidLoad
之后执行didRegisterForRemoteNotificationsWithDeviceToken
,这就是字符串为空的原因

要解决时间问题,您可以这样做

  • AppDelegate
    中声明弱属性

    weak var viewController : ViewController? 
    
  • ViewController
    viewDidLoad
    中设置属性。您不需要
    保护
    AppDelegate
    。如果没有它,应用程序就不会启动

    override func viewDidLoad() {
        print("inside viewDidLoad ")
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.viewController = self
    }
    
  • ViewController
    put中,加载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!)
    

为什么不将设备令牌字符串保存到您的用户默认值?竞争条件问题,我猜您试图在将设备令牌分配给DeviceTokensting in-app delegate之前获取设备令牌。是的,似乎这就是问题所在。有没有办法修复它?广播本地通知或CompletionClose。为什么不将设备令牌字符串保存到您的userdefaults?竞争条件问题,我猜您试图在将设备令牌分配给deviceTokenString in-app delegate之前获取设备令牌。是的,似乎这就是问题所在。有没有办法修复它?要么广播本地通知,要么完成关闭。解释得很好。但是我有一个疑问,如果总是在viewController的
viewDidLoad
之后执行
ApplicationDiFinishLaunching
,那么为什么控制台会打印这个顺序:是的,在viewDidLoad内部?相反,它应该在viewDidLoad中,是的!现在,这是有道理的,解释得很好。但是我有一个疑问,如果总是在viewController的
viewDidLoad
之后执行
ApplicationDiFinishLaunching
,那么为什么控制台会打印这个顺序:是的,在viewDidLoad内部?相反,它应该在viewDidLoad中,是的!现在,这是有道理的