Lets say I have 2 classes.
One is the well known ViewController (that is set to be the custom class of the first scene in the Interface Builder).
And another class, lets call it B, that I created to draw something inside another view that is a sub view of the main view.
Since I have to get notified whenever some values changes in the sub view in order to do some things in the view controller, I decided to use the delegate pattern.
So I set up the protocol in the B class, but now I have to link the delegate to the view controller class. How can I manage to get the view controller class from the class B?
By the way I instantiate some things using override function willMove(toSuperview newSuperview: UIView?) in B. Can I maybe use newSuperView to get the view controller?
I know it is not the best approach since it may break the MVC Pattern, but I don't know which better way to do this.
To get an idea of what I mean you can look at the image.
Related
I have a UIView which I am using as a seperate module and can include it anywhere I want to. Now I want to navigate to a UIViewController on click of the button inside the UIView.
Hope this is pretty clear.
Short answer: You shouldn't. You need to read up on the MVC design pattern. A UIView is a view object. You are trying to add controller behavior to a view object.
You should take a look at parent/child view controllers, container views, and embed segues. You could easily create a view controller that manages a "tile" inside another view controller, and sends messages to it's parent when the user taps buttons. This is a very common way of doing things.
The best way to do this is to supply the ViewController to the view as a delegate, conforming to a protocol you create for it.
For instance, if you UIView is used to pick an image, then the delegate should have a method akin to:
(void)view:(UIView*)view choseImage:(UIImage*)image;
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.
Is there any way that could send the value in Class of ViewController to Class of View?
Because I want to make a drawing board and I made a modal scene to set values about color, width .
I know how to send the value in modal scene to my ViewController , but now I need use those value in Class of View , or not Class of ViewController.
Sounds like you need to devise a protocol to open a delegation channel between the two classes. Then when the modal VC wants to send data to its delegate (its presenter, in this case), it can of its own volition.
The View Controller can have a reference to the View, therefore the View Controller can simply pass the values to View by calling a View's method or updating View's properties. This is a common pattern: View defines a Protocol and data/requests from View to ViewController go through this Protocol (the ViewController acts as delegate of View); and ViewController owns the View.
For inspiration on how to implement a farily decoupled design applying this pattern, you can have a look at documentation on UICollectionView and UICollectionViewController.
Other options, depending on what design you need, are Key-Value Observing or Notifications.
I need to implement an accordion control for iOS. By accordion, I mean a UI like this:
I see two basic ways to do this, but I'm not sure which one to choose.
Method #1: Create a ViewController container, something like a UITabBarController, except that instead of showing tabs at the bottom, I draw a vertical stack of buttons, and when you tap one, the corresponding panel opens and shows the corresponding view controller's view.
Method #2: Create a composite view, add a bunch of views directly to it, and show/hide them as needed.
How do I choose here? What would make me want to treat the sub-units as view controllers vs views?
Generally speaking, if I can avoid it I try not to subclass UIView and instead do everything within UIViewController subclasses. A controller is usually required anyway (model/view glue code, user interaction, delegate stuff, notification handling, etc.), so if no custom drawing is needed it is usually possible to do without a UIView subclass.
In your case I could envision one reusable UIViewController subclass that represents a list entry. It has the following responsibilities:
Create two alternate view hierarchies (collapsed/button, expanded/panel)
Toggle between the view hierarchies in reaction to user interaction (with/without animation)
And another UIViewController subclass that represents the entire list. It has the following responsibilities:
Override the appropriate methods from UIViewController to make it into a container VC
Add/remove child VCs as appropriate to the internal model
Possibly adjust the container view in reaction to collapse/expand events in its child VCs
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