2016-04-04 11 views
1

私は表示したい画像へのパスを含むリモートプッシュ通知から電話を受けています。iOS AppDelegateからView Controller関数を呼び出すにはどうすればよいですか?

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 
} 

...とビューは次のようになります:

AppDelegateである

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に関するいくつかの関連する回答を見つけました上にnced)しかし、何も働かない。

+0

あなたは、VC変数への強い参照を保持していましたか? –

+0

通知を受け取ったときにそれが実際にコードであれば、View Controllerの新しいインスタンスが作成されます。新しいインスタンスのUIは、表示されるまで初期化されないため、イメージビューはnullです。すでに画面に表示されているビューコントローラへのポインタを取得し、新しいコントローラを作成する必要はありません。 – Simon

+0

@Simonだから私はそのメソッドの1つを呼び出すことができるように、appdelegateから既存のView Controllerへのポインタをどのように取得するのですか? – sagism

答えて

4

新しいビューコントローラをモーダルに表示する場合は、さらにレイクの答えを確認してください。

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

2番目のものが動作します(小さな編集後)!ありがとう! – sagism

1

@IBOutlet weak var poolImage: UIImageView!を呼び出して、poolImageの初期化をストーリーボードに渡しています。ビューコントローラをlet vc = ViewController()で初期化するので、vcpoolImageへの参照がクラス内で宣言されていることが予想されることがわかりますが、実際にはvcのビュー(およびサブビュー)を初期化していないため残っていますpoolImage UIがロードされるまでnilにします。

あなたがvcの初期化時にUIImageViewを参照する必要がある場合は、手動でインスタンス化する必要があります:let poolImage = UIImageView()

EDIT:

class ViewController : UIViewController { 

    @IBOutlet weak var poolImage : UIImageView! 

    // rest of file 

} 
poolImageのあなたの ViewController実装では、現在このようになります。

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です。

+0

あなたが提案している初期化をどのように/どこで実行するのか明確ではありません – sagism

+0

@sagismは私の編集を参照してください – Wes

+0

ありがとう、それは表示されるはずのイメージビューではなく、新しいビューです。したがって、画像は表示されません。 – sagism

1

私はあなたが

let vc = ViewController() 

を呼び出している時点で、それをインスタンス化するためには至っていないと信じています。 UIImageViewに@IBOutletを使用しているので、私はあなたが実際にその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

いいえ喜び:(AppDelegateのタイプの値にメンバー 'storyboard'はありません – sagism

+0

私の編集された答えを見て、正しい方向にあなたを助けるかどうかを確認してください – rach

+0

ありがとうございますが、まだ動作しません: 'UIViewController'メンバ 'loadimage' – sagism

0

imageViewinitializedされていないかもしれないので、私が思う理由があります。次の解決策を試してください。

viewControllerに別のinitメソッドを追加すると、URLStringを受け入れます。push notificationを受け取ったらviewControllerinitializeを受け取り、imageURLを新しいinitメソッドに渡します。

新しいinitMethodの中には、imageURLを使用して画像をダウンロードし、imageViewに設定することができます。今度はimageViewnullであってはならず、エラーは発生しません。

+0

問題を解決しませんビューはまだゼロです – sagism

関連する問題