3
votes

I'm creating an app that implements a Facebook and a Twitter service. In my view I have a button that toggles sharing on Facebook/Twitter or not. If Facebook/Twitter aren't connected, then the button will show "connect to".

When I click the button, a method in my controller (not my viewcontroller) will try to toggle the value because this controller tracks the state of my app. When I'm not connected to a social network my controller will notice and will call the correct service. This service will start a webview to provide the user credentials.

And now my question:

When I'm in my service and I need to provide credentials via a webview. When I want to show this webview I need to pass a View Controller that will handle the presenting. How do I provide a viewcontroller here?

Approaches I found:

  • Call the appdelegate singleton and get the current presenting viewcontroller (I find this dirty but correct me if I'm wrong).
  • Since I'm injecting my service into my controller in appdelegate.didFinishLaunchingWithOptions I could inject the UIWindow of the appdelegate and ask for the current presenting viewcontroller (Is almost the same as the first approach)
  • Create a protocol implemented by a viewcontroller. The service has a property that is equal to that protocol and in my app delegate inject the viewcontroller into the service.
  • Have a property in your controller that will be the presentingviewcontroller and let your controller implement the approach #3 protocol. When a function of that protocol is fired, the controller will handle it and use the presentingviewcontroller property for the webview. I only need to inject a viewcontroller into my controller in the appdelegate.
  • Don't implement anything view related in that service.

My current implementation is approach #3.

If some things are not clear, please let me know.

Any help is appreciated! Thanks in advance!

1
Can you tell me name and type of all the classes you used in your query?Sukhpal Singh
Not sure what you mean by types/classes in your query. Could you please give some more information?Mathias Van Houtte

1 Answers

2
votes

I was hoping this question would of got more attention, I was interested to know how other people would handle this situation.

As you have already stated, there are a few ways to achieve what you need, but the answer depends on having knowledge of the application.

I would definitely try to keep business logic and UI as separate as possible, there are two methods that I can think of to do this, but they are pretty much the same thing.

  1. Make the (non UI) controller responsible for the login check with a callback function, you can then leave the controller responsible for business logic and the calling ViewController responsible for rendering any UI as a result of that check.

  2. As you suggested, using protocols, your controller could have a delegate that will be a ViewController that conforms to your protocol. Then usage would just be getting your shared instance, setting the delegate and calling the required fuctionality.

I would likely favor option 2 to be more Swift-like as it is a protocol orientated language.

If the controller is acting globally and accessed from anywhere within the application you could potentially end up duplicating a lot of code to make these checks, you could get around this by creating an extension of UIViewController which provides the functionality to interact with the controller.

I hope this helps, Would definitely be interesting to see the way other people would approach this.