[英]How can I call a view controller function from an iOS AppDelegate?
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: 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
}
...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. 我收到一个异常,说imgView
为null(它声明为@IBOutlet weak var poolImage: UIImageView!
并且可以通过从以下位置调用loadImage("http://lorempixel.com/400/200/")
显示图像单击。
I found a couple of related answers on stackoverflow (one is referenced above) but none work. 我在stackoverflow上找到了几个相关的答案(上面已提及一个),但没有任何效果。
If you want to show a new view controller modally, then look into rach's answer further. 如果您想模态显示一个新的视图控制器,请进一步研究rach的答案。
If you're ViewController is already on screen, you will need to update it to show the information you need. 如果您已经在屏幕上查看ViewController,则需要对其进行更新以显示所需的信息。
How you do this will depend on your root view controller setup. 如何执行此操作将取决于您的根视图控制器设置。 Is your view controller embedded in an UINavigationController? 您的视图控制器是否嵌入在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)
}
}
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. 由于您将@IBOutlet用于UIImageView,因此我假设您实际上具有该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()
By calling @IBOutlet weak var poolImage: UIImageView!
通过调用@IBOutlet weak var poolImage: UIImageView!
you're passing the initialization of poolImage
to the storyboard. 您正在将poolImage
的初始化poolImage
到情节poolImage
。 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. 由于您正在使用let vc = ViewController()
初始化视图控制器,因此vc
将知道它应该引用poolImage
因为您在类中声明了它,但是由于您实际上并未初始化vc
的视图(和子视图) poolImage
保持为零,直到加载UI。
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()
如果在vc
初始化时需要引用UIImageView
,则必须手动实例化它: let poolImage = UIImageView()
EDIT: Your ViewController
implementation of poolImage
currently looks like this: 编辑:您的poolImage
ViewController
实现当前如下所示:
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: 要通过let vc = ViewController()
从AppDelegate
访问poolImage
,您必须使实现看起来像这样:
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. 这样,在创建ViewController
时,它的poolImage
可供参考。
The reason I think is because the imageView
may not have been initialized
. 我认为的原因是因为imageView
可能尚未initialized
。 Try the following solution. 请尝试以下解决方案。
Add another init
method to your viewController
which accepts a URLString
. 向您的viewController
添加另一个init
方法,该方法接受URLString
。 Once you receive a push notification
, initialize
your viewController
and pass the imageURL
to the new init
method. 收到push notification
,请initialize
viewController
并将imageURL
传递给新的init
方法。
Inside the new initMethod
, you can use the imageURL
to download the image and set it to the imageView
. 在新的initMethod
内部,可以使用imageURL
下载图像并将其设置为imageView
。 Now your imageView
should not be null
and the error should not occur. 现在,您的imageView
不应为null
,也不会发生错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.