如何从iOS AppDelegate调用视图控制器函数?
我正在接收来自远程推送通知的呼叫,其中包含要显示的图像的path。
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!) } } }
我得到一个exception,说imgView
是空的(它被声明为@IBOutlet weak var poolImage: UIImageView!
我可以通过调用loadImage("http://lorempixel.com/400/200/")
来显示图像button点击。
我在stackoverflow上find了几个相关的答案(一个是上面引用的),但都没有工作。
如果你想以模态方式显示一个新的视图控制器,那么请进一步查看rach的答案。
如果你的ViewController已经在屏幕上,你将需要更新它来显示你需要的信息。
你如何做到这一点将取决于你的根视图控制器设置。 你的视图控制器embedded在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) } }
通过调用@IBOutlet weak var poolImage: UIImageView!
你将poolImage
的初始化poolImage
给故事板。 由于你正在初始化视图控制器let vc = ViewController()
, vc
会知道,因为你在类中声明它,所以期望有一个对poolImage
的引用,但是因为你实际上没有初始化vc
的视图和子视图)在加载UI之前, poolImage
保持零。
如果您需要在vc
初始化时引用UIImageView
,则必须手动实例化它: let poolImage = UIImageView()
编辑:你的ViewController
实现的poolImage
目前看起来像这样:
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 } }
这样,当创buildViewController
时, poolImage
可供参考。
我相信在你打电话的时候
let vc = ViewController()
它还没有被实例化。 既然你正在为你的UIImageView使用@IBOutlet,我假设你实际上有UIViewController。
也许这可以通过这个纠正:
let vc = self.storyboard?.self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerStoryboardID") vc.loadImage("imageUrl") self.presentViewController(vc!, animated: true, completion: nil)
让我知道如果它的作品。 🙂
编辑:你可以通过这个方法调用storyboard的一个实例:
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()
我认为的原因是因为imageView
可能没有被initialized
。 尝试以下解决scheme。
添加另一个init
方法到你的viewController
接受一个URLString
。 一旦你收到push notification
, initialize
你的viewController
并将imageURL
传递给新的init
方法。
在新的initMethod
,你可以使用imageURL
来下载图像并将其设置为imageView
。 现在你的imageView
不应该是null
,错误不应该发生。