Swift protocol for UIViewController subclasses - ios

Is it possible to declare a protocol and also define the type of object that can conform to it?
I have a set of closures that I'd like to configure in various different subclasses of UIViewController in my project. (They are all related).
I'd like to have a factory function that creates the correct type of UIViewController subclass but then returns it as a protocol type.
That way I can then configure the various closures and push the view controller onto the navigation controller.
I can either...
Return the UIViewController superclass and push it onto the navigation stack but then not be able to set the closures properly as the compiler doesn't know it conforms to the protocol.
or...
Return the protocol type and I'm able to set the closures properly but then the compiler doesn't know that it's a UIViewController subclass so I can't push it onto the navigation controller.
Is there a way to do both?
Thanks

In Objective C you were able to declare a variable like this:
UIViewController <Protocol> *variable;
Unfortunately, this is not possible with Swift, which considering how protocol-oriented Swift is, it's very strange.
This is pretty uncomfortable because like you found out, the compiler can't be aware of both the class and the protocol at the same time, so you have to cast twice, you have to check that the object is of the allowed class at runtime, and have to document it in your code to prevent people from sending the wrong kind of object.

Yes you can!
Do it like this..
// a protocol to make sure the the conforming object is subclass of UIViewController
public protocol IamViewController { }
//make every UIViewController adopt the IamViewController protocol
extension UIViewController:IamViewController { }
//create your protocol and add a requirement that it must be UIViewController if it want to conform to it
protocol vcObject:IamViewController{ }

Related

How do you use UIViewControllerTransitionCoordinator?

The documentation of UIViewControllerTransitionCoordinator isn't very detailed. It implies that you may want to implement this protocol in rare circumstances, but UIViewControllerTransitionCoordinator implements UIViewControllerTransitionCoordinatorContext, which means that you have to implement over a dozen(!) methods to conform to the protocol. I've seen some other people using it by accessing the transitionCoordinator property of a UIViewController while it is being presented, usually in viewWillAppear. However, the documentation implies that viewWillAppear is not the right place to implement either. How are you supposed to make use of this protocol and synchronize animations with those of a presenting view?

ios - Multiple Delegates for a ViewController

I have a ViewController that acts like a Container for two VCs. This class is called MasterDetailViewController. Is a Custom View Controller Container. The MasterDetailViewController can communicate to either the Master or the Detail View Controller so they know status of for example: "Animation of showing detail ViewController started", "Visible rect for VC" and messages like that. The problem is that I need different methods for a master and different methods for a detail.
Is it ok to have two protocols:
MasterViewControllerDelegate
DetailViewControllerDelegate
And the MasterViewController has two properties delegateM and delegateD each conforming to each protocol?
I ask this because the delegate pattern is a 1:1 relationship and I ve never seen it used like this.
Thanks
What I do in this kind of case is pass a weak reference of the master controller to any of its sub-controllers. I don't call them delegates. A delegate protocol makes sense when a wide variety of classes can use the same delegate protocol. In this case, just call it like it is.

Connecting Objects with two View controllers in Swift

In my project I have two view controllers, and I am having trouble connecting objects such as an UIImageView to the view controller. When I try to create the IBOutlet, it tells me that "Could not insert new outlet collection: could not find any information for the class named UIViewController". I believe this problem stems from the fact that my original declaration of my class is as follows:
class UIViewController: UIViewController {
when in fact the view controller is named mainScene instead. However, when I change the first UIViewController to what I think it should be (mainScene), it doesn't even show me the option of connecting an IBOutlet...
class mainScene: UIViewController {
So, I have two questions.
Do I need to have a whole separate class for the second UIViewController and would that solve my issues?
Is there a better way to link objects to the UIViewController or am I just doing something horribly wrong (the likely scenario)?
Thanks so much
Short answer: 1. Yes, and yes. 2. There's no better way, and you're not doing something horribly wrong. (You probably just missed a step.)
You have two view controllers. Assuming they are different, you would subclass each one from UIViewController with a different name. E.g., mainSceneViewController and otherSceneViewController.
Your mainSceneViewController and otherSceneViewController would each have their own properties and IBOutlets.
Where you're probably stuck, is needing to change the class of your viewController within Interface Builder to match the class name in its .swift file, so IB knows what outlets it can connect for that view controller.
Each scene in your storyboard corresponds to a view controller. When the segue is performed, iOS instantiates your view controller from the storyboard.
While it is possible to only have one view controller subclass, and use the same subclass for different views, it doesn't happen too often.
Update:
Subclassing lets you add properties and methods to a class, and override their superclass.
In your comment, UIViewController is the class, and mainSceneViewController is subclassed from UIViewController. For your second view controller, it would likely be class otherSceneViewController: UIViewController {, as your other scene would likely require a different properties and methods from your main scene view controller.
You can read more about Inheritance in the Swift Programming Language guide.

Create base class of UIViewController with tableview and buttons

I want to create base class of UIViewController with tableview for my App sharing functionality between two almost similar ViewControllers.
When i Extend UIViewController with tableview did the child class get access to all views of its superViewController and all the (IBAction)undoAction:(id) sender methods?
Yes that should work. If you subclass a UIViewController (or any other NSObject) you will be able to access all of its (public) methods. You can create a public method by defining them in the header file and adding an implementation of that method in the implementation file. These files will both be created while creating a cocoa (touch) class. The same thing applies to properties, the one you define in the header file will be accessible.
Let me know if you have any further questions

Will a UIViewController subclass also affect my UITableViewControllers?

I need to add a common method to all my view controllers no matter what type they are. I notice though that some of my viewcontrollers inherit from UIViewController and some from UITableViewControllers.
How do I write a subclass that can be used for both?
UITableViewController inherits from UIViewController, so if you want to be able to call your custom method from both, you can write a category on UIViewController and then call methods from that category in any subclass of either UIViewController or UITableViewController. Here's a link to Apple's docs on categories and extensions. http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html
if you add a category to UIViewController, you will be able to call those methods on UITableViewController subclasses, as UITableViewController is a subclass of UIViewController

Resources