0

I got this

#if os(iOS)
import UIKit
import Foundation
#elseif os(OSX)
import Foundation
import cocoa
#else
// Future concerns
#endif


enum Image: String {
    case Preferences
    ....
    case App
    case Stop
    ....
    case Default


    #if os(iOS)
    func image(selected: Bool = false) -> UIImage? {
        let imgName : String = selected ? self.rawValue + "-selected" : self.rawValue
        if let img = UIImage(named:imgName) {
            return img
        } else {
            print("iOS")
            print("Please add the \(imgName) icon to the app assets!!")
            //Creating the alert
            let alertController = UIAlertController(title: "Icon Missing", message: "Please add the \(imgName) image to the app assets!!", preferredStyle: .alert)
            let action = UIAlertAction(title: "I Promiss I will", style: .default, handler: nil)
        alertController.addAction(action)
        // How to get the alert working
     self.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
       //
            return nil
        }
    }
    #elseif os(OSX)
    func image(selected: Bool = false) -> NSImage? {
        ....
    }
    #else
    //
    #endif
}

I know enum doesn't have a self.window, I just type this line (self.window?.rootViewController?...) to show the issue. Is there away to get the alert working? Of course I don't want to submit a view object to the Image.Question.image(). Also if it will be used in a later phase in the development will be debatable, but still want to know if there is a way.

Thank you in advance.

======== Solved =========

With the info and comment from k.zoli, my main issue did get solved.

resulting code

func image(selected: Bool = false) -> UIImage? {
        let imgName : String = selected ? self.rawValue + "-selected" : self.rawValue
        guard let img = UIImage(named: imgName) else {
            print("iOS")
            print("Please add the \(imgName) icon to the app assets!!")
            //Creating the alert
            let alertController = UIAlertController(title: "Icon Missing", message: "Please add the \(imgName) icon to the app assets!!", preferredStyle: .alert)
            let action = UIAlertAction(title: "I Promiss I will", style: .default, handler: nil)
            alertController.addAction(action)
            if let window = UIApplication.shared.delegate?.window { DispatchQueue.main.async { window?.rootViewController?.present(alertController, animated: true, completion: nil) } }
            return nil
        }
        return img
    }
iPadawan
  • 898
  • 1
  • 12
  • 23
  • solved so far by k.zoli - unfortunate not useable in viewDidLoad func – iPadawan Sep 10 '18 at 13:05
  • in viewDidLoad, I get a crash because there is no view yet is the list "Test.ViewController: 0x7fdb21c07bc0> whose view is not in the window hierarchy!". After the view is visible, the view is in the hierarchy" then it works. In viewDidAppear there it works. However I do the image setup in viewDidLoad. With the latest sample of k.zoli it works great also in viewDidLoad. – iPadawan Sep 10 '18 at 16:04

1 Answers1

0

You can get access to the current window through UIApplication's shared instance.

if let window = UIApplication.shared.delegate?.window {
        window?.rootViewController?.present(alertController, animated: true, completion: nil)
    }
k.zoli
  • 41
  • 8
  • Great idea. Always forget about UIApplication. Unfortunate I get "Test.ViewController: 0x7fdb21c07bc0> whose view is not in the window hierarchy!" – iPadawan Sep 10 '18 at 12:16
  • Sorry your right - It does work when the view is visible. Not yet of course in ViewDidLoad func, and thats the place where I setup the images. So it looks like a 'no can do'. Not yet enough points. If people give me some points for my question I can add a point to your answer. Anyway, thank you very much. – iPadawan Sep 10 '18 at 13:02
  • As you can see here: https://stackoverflow.com/a/34692351/4696911 Try this or call this setup from viewDidAppear: if let window = UIApplication.shared.delegate?.window { DispatchQueue.main.async { window?.rootViewController?.present(alertController, animated: true, completion: nil) } } – k.zoli Sep 10 '18 at 13:48
  • did put your code in the enum image func and it works. It wait till the view is in the hierarchy/visible and then the alert comes forward. I still can do my setup in viedDidLoad. One thing I can't figure out is when I have two calls to the enum.image func, f.e the Question and the App image, like ( let imageQuestion =Image.Question.image() let imagePreferences =Image.Preferences.image(selected:true) ), I just see one alert. - I have to figure out what is nice, 1. to let the app bail out after one alert, 2. add also a default replacement image, 3 an alert with a list of missing images – iPadawan Sep 10 '18 at 16:02
  • You can find the [topViewController](https://stackoverflow.com/a/48417467/4696911) But, I think this results a bad user experience. Multiple alert may confuse the user. – k.zoli Sep 10 '18 at 21:00