繁体   English   中英

如何从iOS AppDelegate调用视图控制器函数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM