如何从iOS AppDelegate调用视图控制器功能?

时间:2016-04-04 15:57:49

标签: ios swift apple-push-notifications

我正在通过远程推送通知接听电话,其中包含我想要显示的图像路径。

AppDelegate是:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    // get url from notification payload (shortened version)
    let url = alert["imgurl"] as? NSString 
    let vc = ViewController()
    vc.loadImage(url as String) // cannot find the imageView inside
}

...视图如下:

func loadImage(url:String) {
    downloadImage(url, imgView: self.poolImage)
}

// http://stackoverflow.com/a/28942299/1011227
func getDataFromUrl(url:String, completion: ((data: NSData?) -> Void)) {
    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) { (data, response, error) in
        completion(data: NSData(data: data!))
        }.resume()
}

func downloadImage(url:String, imgView:UIImageView){
    getDataFromUrl(url) { data in
        dispatch_async(dispatch_get_main_queue()) {
            imgView.image = UIImage(data: data!)
        }
    }
}

我收到异常,说imgView为空(声明为@IBOutlet weak var poolImage: UIImageView!,我可以通过点击按钮调用loadImage("http://lorempixel.com/400/200/")来显示图片。

我在stackoverflow上找到了几个相关的答案(一个在上面引用)但没有工作。

4 个答案:

答案 0 :(得分:4)

如果您想以模态方式显示新的视图控制器,请进一步查看rach的答案。

如果您的ViewController已经在屏幕上,则需要更新它以显示您需要的信息。

如何执行此操作取决于您的根视图控制器设置。您的视图控制器是否嵌入在UINavigationController中?如果是这样,那么试试这个:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    if let rootViewController = window?.rootViewController as? UINavigationController {
        if let viewController = rootViewController.viewControllers.first as? ViewController {
            let url = alert["imgurl"] as? NSString
            viewController.loadImage(url as String)
        }
    }
}

如果不是,那就试试这个:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    if let rootViewController = window?.rootViewController as? ViewController {
        let url = alert["imgurl"] as? NSString
        rootViewController.loadImage(url as String)
    }
}

答案 1 :(得分:2)

我相信你打电话的时间

let vc = ViewController()

尚未实例化。由于您正在为UIImageView使用@IBOutlet,我假设您确实拥有该UIViewController。

也许可以通过这个纠正:

let vc = self.storyboard?.self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerStoryboardID")
vc.loadImage("imageUrl")
self.presentViewController(vc!, animated: true, completion: nil)

让我知道它是否有效。 :)

编辑:你可以通过这种方法调用故事板的实例:

self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

var storyboard = UIStoryboard(name: "Main", bundle: nil)

var vc = storyboard.instantiateViewControllerWithIdentifier("ViewController") as! UIViewController

vc.loadImage("imageUrl")

self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()

答案 2 :(得分:1)

通过调用@IBOutlet weak var poolImage: UIImageView!,您将poolImage的初始化传递给了故事板。由于您使用let vc = ViewController()初始化视图控制器,vc会知道它应该引用poolImage,因为您在课程中声明了它,但是因为您不是实际初始化vc的视图(和子视图)poolImage在UI加载之前仍为零。

如果您需要在初始化UIImageView时引用vc,则必须手动实例化它:let poolImage = UIImageView()

编辑:您ViewController的{​​{1}}实施目前看起来像这样:

poolImage

要从class ViewController : UIViewController { @IBOutlet weak var poolImage : UIImageView! // rest of file } 通过poolImage访问AppDelegate,您必须使实施看起来像这样:

let vc = ViewController()

这样,class ViewController : UIViewController { /* ---EDIT--- add a placeholder where you would like poolImage to be displayed in the storyboard */ @IBOutlet weak var poolImagePlaceholder : UIView! var poolImage = UIImageView() // rest of file override func viewDidLoad() { super.viewDidLoad() /* ---EDIT--- make poolImage's frame identical to the placeholder view's frame */ poolImage.frame = poolImagePlaceholder.frame poolImagePlaceholder.addSubView(poolImage) // then add auto layout constraints on poolImage here if necessary } } 可在创建poolImage时供参考。

答案 3 :(得分:0)

我认为原因是因为imageView可能不是initialized。尝试以下解决方案。

将另一个init方法添加到接受viewController的{​​{1}}。收到URLString push notification initializeviewController并将imageURL传递给新init方法。

在新initMethod内,您可以使用imageURL下载图片并将其设置为imageView。现在,您的imageView不应为null,并且不应出现错误。