[英]How can I call a view controller function from an iOS AppDelegate?
我收到来自远程推送通知的呼叫,该通知包括要显示的图像路径。
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
为null(它声明为@IBOutlet weak var poolImage: UIImageView!
并且可以通过从以下位置调用loadImage("http://lorempixel.com/400/200/")
显示图像单击。
我在stackoverflow上找到了几个相关的答案(上面已提及一个),但没有任何效果。
如果您想模态显示一个新的视图控制器,请进一步研究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)
}
}
我相信在您打电话的时间点
let vc = ViewController()
它尚未实例化。 由于您将@IBOutlet用于UIImageView,因此我假设您实际上具有该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()
通过调用@IBOutlet weak var poolImage: UIImageView!
您正在将poolImage
的初始化poolImage
到情节poolImage
。 由于您正在使用let vc = ViewController()
初始化视图控制器,因此vc
将知道它应该引用poolImage
因为您在类中声明了它,但是由于您实际上并未初始化vc
的视图(和子视图) poolImage
保持为零,直到加载UI。
如果在vc
初始化时需要引用UIImageView
,则必须手动实例化它: let poolImage = UIImageView()
编辑:您的poolImage
ViewController
实现当前如下所示:
class ViewController : UIViewController {
@IBOutlet weak var poolImage : UIImageView!
// rest of file
}
要通过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
}
}
这样,在创建ViewController
时,它的poolImage
可供参考。
我认为的原因是因为imageView
可能尚未initialized
。 请尝试以下解决方案。
向您的viewController
添加另一个init
方法,该方法接受URLString
。 收到push notification
,请initialize
viewController
并将imageURL
传递给新的init
方法。
在新的initMethod
内部,可以使用imageURL
下载图像并将其设置为imageView
。 现在,您的imageView
不应为null
,也不会发生错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.