1

I am developing an SDK which will be called by some client UI. The SDK comprises various modules that perform different tasks. One of the modules, on receipt of a url, must open a video popup or equivalent to playback the video. The module itself is a normal class that does not have UI.

While I am able to launch a UIAlertController popup from the class, when I try to launch a UIViewController to play back the video I hear audio without seeing the video. What is the suggested way of

  1. Launching a viewcontroller from a non UI class
  2. Showing the video as a popup window with controls

Thanks

Luke Van In
  • 5,215
  • 2
  • 24
  • 45
Dave Honly
  • 568
  • 1
  • 4
  • 5
  • You can add a UIView to application window. UIWindow *appWindow = ((AppDelegate*)[UIApplication sharedApplication].delegate).window; – gurmandeep Jul 14 '16 at 16:00
  • 2
    It's generally shaky ground to present view controllers from frameworks. But if you really need to, access the `[UIApplication sharedApplication].keyWindow.rootViewController` and walk the view hierarchy until you get to the top controller https://gist.github.com/MartinMoizard/6537467 http://stackoverflow.com/questions/15961288/presenting-a-modal-controller-without-knowing-the-current-view-controller – markedwardmurray Jul 14 '16 at 16:05

1 Answers1

1

If your SDK needs to be compatible with app extensions, then UIApplication will be unavailable for you to use.

To work around this, while also giving the host application greater control, you can implement a delegate which presents the view controller for the SDK.

The host application can implement the delegate and choose the most appropriate controller, including using the root view controller as recommended by Mark.

First declare a protocol:

public protocol MySDKPopupDelegate: NSObjectProtocol {
    func presentPopupViewController(viewController: UIViewController)
}

Define a way to set the delegate in the SDK:

public class MySDKConfig {

    public let sharedConfig = MySDKConfig

    weak var delegate: MySDKPopupDelegate?
}

When your SDK needs to present the video, request the view controller from the delegate:

func showPopupForVideo(url: NSURL) {
    let viewController = viewControllerForVideo(url)
    delegate?.presentPopupViewController(videoViewController)
}

Finally, the host application should implement the delegate method to actually present the view controller, for example, in the AppDelegate:

class AppDelegate: NSObject, MySDKPopupDelegate {

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        MySDKConfig.sharedConfig.delegate = self
    }


    func presentPopupViewController(viewController: UIViewController) {

        guard let presentingViewController = window?.rootViewController else {
            return
        }

        presentingViewController.presentViewController(viewController, animated: true, completion: nil)
    }
}

The delegate can also be implemented in a specific view controller, including in an app extension:

class ShareViewController: UIViewController, MySDKPopupDelegate {

    override public func viewDidLoad() {
        MySDKConfig.sharedConfig.delegate = self
    }

    func presentPopupViewController(viewController: UIViewController) {
        presentViewController(viewController, animated: true, completion: nil)
    }
}
Luke Van In
  • 5,215
  • 2
  • 24
  • 45
  • Cheers Luke. Works nicely. It is necessary to implement the delegate in the specific view controller you want to appear on top of (which I guess makes sense). – Dave Honly Jul 15 '16 at 08:00
  • It really depends on the view hierarchy, sometimes you can get away with the rootviewcontroller if the hierarchy is flat. – Luke Van In Jul 15 '16 at 08:03