4

I read this post and this one on how to call a presentViewController form outside a UIViewController subclass. In my case, the custom class is a subclass of NSObject. The following approach is the only one that works (from the examples I read):

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

My question: is there a better solution that does not rely on the appDelegate (as I understood this approach is design-wise not very neat)...

Community
  • 1
  • 1
Pieter
  • 2,621
  • 4
  • 19
  • 26

3 Answers3

11

I sometimes create a utilities class to display alerts and such. What I usually do is have my methods for presenting view controllers take the current view controller as a parameter. That approach works pretty well.

EDIT:

Here is an example method from a file Utils.swift in one of my projects. It defines a class function that displays a UIAlertController alert on the current view controller:

class Utils
{
  static let sharedUtils = Utils()
  
  class func showAlertOnVC(
    targetVC: UIViewController, 
    var title: String, 
    var message: String)
  {
    title = NSLocalizedString(title, comment: "")
    message = NSLocalizedString(message, comment: "")
    let alert = UIAlertController(
      title: title, 
      message: message, 
      preferredStyle: UIAlertControllerStyle.Alert)
    let okButton = UIAlertAction(
      title:"OK",
      style: UIAlertActionStyle.Default,
      handler:
      {
        (alert: UIAlertAction!)  in
    })
    alert.addAction(okButton)
    targetVC.presentViewController(alert, animated: true, completion: nil)
  }
}

The code above defines a class Utils. Note that it does not have any base class, which is Ok in Swift.

Next it defines a public static variable sharedUtils that you can use to get access to the singleton Utils class.

Finally, it defines a class method showAlertOnVC that can be used to display a UIAlertController alert on top of the current view controller. To use showAlertOnVC you call it from the current view controller and pass self as the targetVC parameter.

Community
  • 1
  • 1
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • And what class does that utilities class subclass? – Pieter May 10 '15 at 20:14
  • Doesn't matter. In Objective-C, NSObject. In Swift, no base class. – Duncan C May 10 '15 at 20:22
  • But that is comparable to my current solution, which also has no base class. My question is how to avoid calling the AppDelegate, which I guess will still be necessary if this class does not subclass a ViewController... – Pieter May 12 '15 at 10:29
  • No. Create a utilities class. Put your methods in that. You can make the methods class methods if they need instance variables, or you can make the utilities class a singleton. Classes in Swift don't have to subclass anything, unlike Objective-C. – Duncan C May 12 '15 at 10:58
  • This seems to work! For clarity, you may consider formatting your code as code. Nevertheless, I accepted your answer... thanks! – Pieter May 13 '15 at 18:27
  • Yup. I tend to type code not indented, and then indent it before posting. In this case I forgot to indent the code before posting. – Duncan C May 13 '15 at 18:56
  • In my comment above I should have said "you can make the methods class methods if they **don't** need instance variables, or you can make the utilities class a singleton." – Duncan C Jan 16 '17 at 20:01
3

This in my opinion is the easiest solution:

class Utils {
  static  func displayTheAlert(targetVC: UIViewController, title: String, message: String){
        let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction((UIAlertAction(title: "OK", style: .Default, handler: {(action) -> Void in
        })))
        targetVC.presentViewController(alert, animated: true, completion: nil)
    }
}

// then to call it

Utils.displayTheAlert(self, title: "Fout", message: "Uw bestelling is nog niet klaar")
Hugo Yates
  • 2,081
  • 2
  • 26
  • 24
Alex Zanfir
  • 573
  • 4
  • 13
2

From the design point of View, it is not advisable for the model class(NSObject) to interact directly with View. It does not conform to the MVC Pattern . Avoid using UIKIT in the NSObject class.

Piyush Vaish
  • 107
  • 8