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.
Related
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.
I am trying to pass instance of object from "initial" view controller to "item1" and "item2". I would like to avoid subclassing UITabBarController as it would make containment view controller know "too much".
Is there any good approach to do that using storyboards or code besides subclassing UITabBarController?
I would like to avoid subclassing UITabBarController as it would make containment view controller know "too much".
You should subclass, and your subclass should implement a specific protocol for this purpose. Yhen, the containing VC only knows about that protocol and it's appropriate because it has that direct responsibility.
I am trying to pass instance of object from "initial" view controller
to "item1" and "item2". I would like to avoid subclassing
UITabBarController as it would make containment view controller know
"too much".
The problem here is that the destinationViewController of your segue is the UITabBarController and not item 1 or item 2. This makes your case quite difficult if you don't want to subclass it, because you can't communicate directly between the instances of your initial VC and the two items.
My recommendation indeed would be to subclass, that's the right way to go in this situation (you might want to add a protocol that specifies the communication interface).
Other options are:
somehow give the initial view controller access to instances of item 1 and item 2 (you'll have to do a lot of this setup in code since Storyboards don't give you the power to do it all completely in IB)
use NSNotification and pass the instances as userInfo (not very elegant but might be the quickest solution for your isse)
store serialized versions of the instances that you want to pass in NSUserDefaults and load them in item 1 and item 2 (might be a lot of overhead)
I'm rather new to programming and wondering about a certain (best) practice:
Let's assume we have an app with several view controllers. In our case, most of those need the functionality of alerting the user about certain circumstances, make use of an activity indicator or depend on other similar general functionality. So far I've learnt how to implement such methods but then just copied the whole bunch of code to each view controller when needed. Doing so, every view controller gets filled up with a lot of extra code. I know it's possible to make code kind of "global" by moving it to the top of a view controller, outside the class brackets. But as we need to ensure that certain subviews are added to the right view controllers when calling those methods I'm not sure yet what the best way to go - in general - would be.
Is there a commonly used practice that differs from my approach when defining such - let's say - alert behaviors (defining variable/constant and its needed methods) which are used in multiple view controllers?
Objective-C provides two general ways of reusing code:
Inheriting a base class, and
Using a shared function.
The first case is straightforward: if you need a specific functionality in several view controllers, make a base view controller with the shared methods, and then derive your other view controllers from it:
#interface BaseViewController : UIViewController
-(void)sharedMethodOne;
-(void)sharedMethodTwo;
#end
#interface FirstViewController : BaseViewController
...
#end
#interface SecondViewController : BaseViewController
...
#end
#interface ThirdViewController : BaseViewController
...
#end
The second case can be implemented either as a helper class with class methods (i.e. with + instead of -) or with free-standing C functions.
You should look to see what could be moved from the controller level to the view level. It sounds like you're reusing a bunch of views so I would create subclasses of UIViews that can implement themselves. Then in the view controller you can handle when the views should appear and the data associated with them but you don't need to rewrite how to implement the views.
I am using the UIViewControllerContainment feature in iOS. My container controller is called mainViewController. It consists of menuViewController and contentViewController. The menuViewController is a UITableViewController.
Now, I want that when I select a row in menuViewController I handle an event inside the mainViewController. I have to do all of this without changing the code of menuViewController.
** I am aware I can use delegates to call the mainViewController but using the delegate will alter ** the menuViewController code which I do not want to do.
Assuming that the menuViewController isn't designed with some sort of delegate or callback block (or you wouldn't be asking the question), you're options are really very limited, and there are no good options, since any option would violate the concept of containment that you're trying to take advantage of.
As I see it, your choices are:
Modify the menuVieController to add a delegate or block callback on item selection. This is the best approach since it keeps the menuViewController well contained and isolated.
Subclass the menuViewController, override didSelectCell... and do number 1. Probably need to make sure you call super as well. This is bad because you're making assumptions about the internal structure of menuViewController and violating containment.
Steal the tableView delegate and handle it yourself. This makes even more assumptions about the internals of menuViewController.
Bottom line, I'd really recommend you rethink the decision not to change menuViewController.
I have 30+ viewcontroller in my project, and there is a behavior to be added in 28 of them.
When a button is clicked if 10 second not passed in that viewcontroller, I need to present a alertview sliding from top. (I have already implemented this behaviour for one of them)
But my question is, how can I inherit this behavior in a proper way for all of these viewcontrollers?
Googling this, but cannot find relavent solutions.
If all of your view controllers that need this functionality are subclasses of UIViewController, i.e. not UITableViewController or another subclass of UIViewController, you can create a subclass of UIViewController, say ButtonClickAlertViewController (or whatever makes sense) that implements the functionality you need to replicate. Then have all of the classes that need this functionality subclass your ButtonClickAlertViewController class instead of UIViewController.
You may need to take into account how this specific functionality integrates into each of your individual view controller classes. For example, you may need a method in your ButtonClickAlertViewController class that signals a button has been clicked in order to check your timer and possibly display an alert. In each of your classes that subclass ButtonClickAlertViewController, you might need to call this method in each of the IBAction methods that your button click actions call.
Subclass UIViewController and add your desired behavior for all view controllers and then subclass your existing view controllers from the viewController with the desired behavior.
Inheritance chain:
UIViewController -> ViewControllerWithBehaviorForAll ->
YouExistingViewlContollersWhichNeedTheBehavior