简体   繁体   English

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

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

相关问题 如何从iOS中的AppDelegate调用视图控制器 - How to call a view controller from AppDelegate in iOS 如何在 Swift 中从 Appdelegate 调用视图控制器中的方法? - how to call a method in a view controller from Appdelegate in Swift? iOS:从AppDelegate访问导航视图控制器 - iOS: Accessing Navigation View Controller From AppDelegate 如何从视图控制器类访问AppDelegate类中声明的对象? - How can I access an object declared in the AppDelegate class from my view controller class? 如何通过iOS Objective C中的appDelegate从另一个视图控制器重新加载表视图 - How to reload table view from another view controller via appDelegate in iOS Objective C 无法从AppDelegate推送到View Controller而不会丢失导航栏和标签栏设置iOS - Can't push to View Controller from AppDelegate without losing Navigation Bar and Tab Bar setup iOS ios xmpp通过appdelegate从oneview控制器调用另一个viewcontroller - ios xmpp call another viewcontroller from oneview controller through appdelegate 如何从场景委托中调用 function,该委托在视图 controller 中下载 URL? - How can I call a function from scene delegate which downloads an URL in a view controller? 无法从AppDelegate调用锁屏视图控制器 - Unable to call Lock Screen view controller from AppDelegate 如何通过appdelegate在选项卡视图控制器中调用方法。 故事板 - how to call a method in a tab view Controller from appdelegate. story board
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM