2016-04-04 2 views
1

Я получаю звонок от удаленного push-уведомления, который включает в себя путь к изображению, который я хочу отобразить.Как я могу вызвать функцию контроллера вида из 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 является недействительным (он объявлен как @IBOutlet weak var poolImage: UIImageView! и I может отображать изображение, позвонив по телефону loadImage("http://lorempixel.com/400/200/").

Я нашел пару связанных ответов на stackoverflow (один из них ссылается но никто не работает.

+0

ли вы сохранить сильную ссылку на В.- переменную? –

+0

Если это ваш код, когда вы получаете уведомление, то вы создаете новый экземпляр вашего контроллера. Представление вашего изображения равно null, поскольку пользовательский интерфейс нового экземпляра не будет инициализирован до тех пор, пока он не будет отображаться. Вам нужно получить указатель на контроллер вашего вида, который уже находится на экране, а не создавать новый. – Simon

+0

@Simon так как я могу получить указатель на существующий контроллер представления из appdelegate, чтобы я мог назвать один из его методов? – sagism

ответ

4

Если вы хотите показать новый контроллер вида по модулю, тогда зайдите в ответ 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) 
    } 
} 
+0

Второй работает (после небольшого редактирования)! Спасибо! – sagism

1

По телефону @IBOutlet weak var poolImage: UIImageView! вы передаете инициализацию poolImage в раскадровку. Поскольку вы инициализируете контроллер вида с помощью let vc = ViewController(), vc будет знать, что ожидается, что он будет иметь ссылку на poolImage, потому что вы объявили его в классе, но поскольку вы фактически не инициализируете вид vc (и в подзаголовках) poolImage остается nil до загрузки пользовательского интерфейса.

Если вам нужно ссылаться на UIImageView в момент инициализации vc, вам придется вручную создать его экземпляр: let poolImage = UIImageView()

EDIT: Ваш ViewController реализация poolImage в настоящее время выглядит следующим образом:

class ViewController : UIViewController { 

    @IBOutlet weak var poolImage : UIImageView! 

    // rest of file 

} 

чтобы получить доступ к poolImage из AppDelegate через let vc = ViewController() вы должны сделать вид реализации, как это:

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 

    } 

} 

Этот способ poolImage доступен для справки, когда создается ViewController.

+0

Непонятно, как и где выполнить инициализацию, которую вы предлагаете – sagism

+0

@sagism Посмотреть мое редактирование – Wes

+0

Спасибо, это инициализирует новое изображение в порядке, но это не образ, который он должен отображать, а скорее новый. Таким образом, изображение не отображается. – sagism

1

Я считаю, что в момент времени, когда вы звоните

let vc = ViewController() 

он еще инстанциируемый. Поскольку вы используете @IBOutlet для своего UIImageView, я предполагаю, что на самом деле у вас есть UIViewController.

Может быть, это можно исправить с помощью этого:

let vc = self.storyboard?.self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerStoryboardID") 
vc.loadImage("imageUrl") 
self.presentViewController(vc!, animated: true, completion: nil) 

Позвольте мне знать, если он работает. :)

EDIT: Вы могли бы назвать экземпляр раскадровки с помощью этого метода:

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() 
+0

No Joy :(Значение типа AppDelegate не имеет «раскадровки» участника – sagism

+0

Взгляните на мой отредактированный ответ и посмотрите, поможет ли он вам в правильном направлении. – rach

+0

Спасибо, но все еще не работает: Значение типа «UIViewController» имеет no member 'loadimage' – sagism

0

Причина, я думаю, это потому, что imageView не может быть initialized. Попробуйте следующее решение.

Добавить еще один метод init к вашему viewController который принимает URLString.Как только вы получите push notification, initializeviewController и передайте imageURL на новый метод init.

Внутри нового initMethod вы можете использовать imageURL, чтобы загрузить изображение и установить его на imageView. Теперь ваш imageView не должен быть null, и ошибка не должна возникать.

+0

Не исправляет проблему. Просмотр по-прежнему ноль. – sagism

Смежные вопросы