可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am getting a call from a remote push notification, which includes a path to an image, which I want to display.
The AppDelegate is:
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
}
...and the view looks like this:
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!)
}
}
}
I'm getting an exception saying imgView
is null (it is declared as @IBOutlet weak var poolImage: UIImageView!
and I can display an image by calling loadImage("http://lorempixel.com/400/200/")
from a button click.
I found a couple of related answers on stackoverflow (one is referenced above) but none work.
回答1:
If you want to show a new view controller modally, then look into rach's answer further.
If you're ViewController is already on screen, you will need to update it to show the information you need.
How you do this will depend on your root view controller setup. Is your view controller embedded in an UINavigationController? If so then try this:
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)
}
}
}
If it is not, then try this:
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)
}
}
回答2:
I believe at the point of time where you are calling
let vc = ViewController()
it has yet to be instantiated. Since you are using @IBOutlet for your UIImageView, I am assuming that you actually have that UIViewController.
Maybe it could be corrected by this:
let vc = self.storyboard?.self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerStoryboardID")
vc.loadImage("imageUrl")
self.presentViewController(vc!, animated: true, completion: nil)
Let me know if it works. :)
EDIT: You could call an instance of storyboard via this method:
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()
回答3:
By calling @IBOutlet weak var poolImage: UIImageView!
you're passing the initialization of poolImage
to the storyboard. Since you're initializing the view controller with let vc = ViewController()
, vc
will know that it is expected to have a reference to poolImage
because you declared it in the class, but since you aren't actually initializing vc
's view (and subviews) poolImage
remains nil until the UI is loaded.
If you need to reference a UIImageView
at the time of the initialization of vc
, you'll have to manually instantiate it: let poolImage = UIImageView()
EDIT: Your ViewController
implementation of poolImage
currently looks like this:
class ViewController : UIViewController {
@IBOutlet weak var poolImage : UIImageView!
// rest of file
}
To access poolImage
from AppDelegate
via let vc = ViewController()
you have to make the implementation look like this:
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
}
}
That way it poolImage
is available for reference when ViewController
is created.
回答4:
The reason I think is because the imageView
may not have been initialized
. Try the following solution.
Add another init
method to your viewController
which accepts a URLString
. Once you receive a push notification
, initialize
your viewController
and pass the imageURL
to the new init
method.
Inside the new initMethod
, you can use the imageURL
to download the image and set it to the imageView
. Now your imageView
should not be null
and the error should not occur.