How to tell an UIView about an event in a collectionviewcell? - ios

Reference Image
Hello!
I'm making a Swift project using the MVC pattern, and I'm hoping you guys could help me with how to best pass information between different classes.
I'll do my best to describe, but please take a look at my badly drawn reference for some additional clarity.
The project is build with a Model, that's a simple class with the rules of the project, a View Controller, that has an instance of both the View and the Model, passes information between them and initiates the View.
The View has all the element variables, and sets the layout. The view has a CollectionViewController, that in turn has the CollectionViewCells. One of those cell has a Button. There's of course some other classes, but they're not relevant.
What I'm trying to accomplish is that I want the user to click the Button in the CollectionViewCell. The CollectionViewCell should then tell the View that the Button was pressed, and the View should take some Information and send to the ViewController, that will interpret it for the Model.
More or less Button > User Clicks -> (CollectionViewController) -> View > View collects Information -> CollectionView -> Model.
I cannot delegate the buttonclick event to the View, as UIViews cannot be delegated to. I can use a Closure to send the buttonclick event to the CollectionViewController, but I don't seem to be able to send it further from there.
So the two alternatives I'm looking at is creating a NotificationCenter just to tell the View a button has been pressed, or making the View a ViewController too. Neither seems ideal. Does anyone have a better solution, or any insight on what I should do here?

One solution based on your reference image can be this:
you can send your click event with clouser to your collectionView parent view and in your view have a weak instance of your parent viewController. when the clouser called, you can call the method from your parent instance and update your model

Related

Accessing function from inside of a subview controller

I am using a walkthrough library written in swift, and I am trying to have the keyboard to be displayed only on a specific step in the walkthrough. If I add a textField to that specific view controller in the storyboard, and make it become the first responder, the keyboard is shown for all of the other view controllers as well. What I am trying to accomplish is when the user is on this specific page, I would like the keyboard to be present, and when they scroll away, for it to disappear with the swipe.
The library offers a function called walkthroughPageDidChange, however it’s on the master view controller where all the subview controllers are attached to. I can check if the pageNumber is the one I want it to be, however I am not sure how to accomplish accessing a function inside of one of the attached view controller pages.
I would like to access the keyboard controller with the following functions:
KeyboardViewController.showKeyboard() - becomeFirstResponser for textField
keyboardViewController.hideKeyboard() - resignFirstResponder for textField
if pageNumber == 2 {
KeyboardViewController.showKeyboard()
}else{
KeyboardViewController.hideKeyboard()
}
How would I accomplish this? How would I be able to access this function inside of another view controller?
Thank you in advance.
You should keep an array of your ViewControllers in the parent ViewController when you create them. So in your array you pick the right controller and call the function you want. I did not see the code where the viewcontrollers are stored in an array your link, but you can just add it where you create the VCs.

Container View with multiple child views issue

I am trying to develop a Table View Controller(having a navigation controller),where rows are connected to multiple View Controllers (TextField,TextView,TableView,DatePicker,ImageView etc.).
So I design like this,if I click on any row,it should open one UIViewController having container view and then place the appropriate controller in the container.All the same type of tableview rows are using same View Controller as a child view of the container.
I am able to place proper view controller(example - 1.TextViewController for Text View
2. Table View Controller for Table view 3. DatePickerController for Date Picker.) in the container depend on their the row type.
But I am little bit confuse about how to pick the data from the child view when I click the done button(2nd screen right top). i.e for child Text Field I have to pick the input data whatever I type in the input box. For child Table view I hide the done button,so as soon as user select the data 'cellForRowAtIndexPath' should get fire and pass the seleted data.
How to do that data handleing? where to write that?
Is there any other way to design this?
As #Suhail mentioned the best way to do it, in general, when you want to pass data from a child view controller to the parent view controller, or in some cases from a controller to previous displayed controllers (that are still in the stack), is by using delegate pattern. You can implement delegate pattern with iOS protocols or with blocks. In my opinion, both approaches have their pros and cons, for that topic you'll have to do little more google search since this is not the place to discuss it.
Let's define some cases for your case(not all the cases):
You want to send data from ChildTableViewControler to Field controller (screen 3 to screen 2)
In this case, from what I understood, both controllers are embedded in a parent controller, so you'll have to set parent to be the delegate to the two child controllers. You have to create one or two protocols depending on your actions or data you want to send to the controllers. Create a property called delegate (you can choose your own name) on each of the children, implement the methods on the parent view controller, whenever you add one of the children on screen, set the delegate property to be the parent view controller. Now whenever you want to send data to the other child, you'll have to call the methods declared in your protocols. Remember, you have access from the parent to both children via childViewControllers propery.
Short version: One/Two protocols for children, parent implements the protocol(s) and responds to child action.
You want to send data from Filed to TableViewController (from screen 2 to screen 1)
In this case you'll declare a protocol in the parent view controller, which will be implemented by the TableViewController.Declare a delegate (or whatever name you like) property in the parent view controller. When you add the Filed controller on screen, you set the delegate property to be the TableViewController. Now you can communicate with the TableViewController from the Field controller via delegate property.
Short version: one protocol in parent view controller, TableViewController implements the protocol and responds to TableViewController actions.
You want to send data from ChildTableViewController to TableViewController (screen 3 to screen 1).
This is the same as case 2.
One of my rule when I send data from view controllers is something like this: if I want to send data forward (to the next screen that will be displayed) then I use property/methods. If I want to send data backwards(to previously displayed controllers) then I use delegate/blocks.
And my last advice, please check the delegate/blocks implementations and how to use them before you start implementing one of the above solutions. You can have lots of troubles if you implement them wrong, especially memory issues and random crashes.
A little bit off topic, if the reader of my answer is a 9gagger then "sorry for the long post, here's a potato"

IBOutlets/actions and custom subview

Apologies if this seems a straightforward question! I'm using AVFoundation to build a custom camera app that allows the user to draw on the image after it's taken (similar to snapchat).
I have the camera functionality working. Currently, after the shutter button is pressed I add (as a subview) a standard UIImageView to display the photo taken. Seeing as I want there to be custom options at this stage (including drawing on the image), I proceeded to create my own subclass of UIImageView. I am designing this view in Interface Builder (xib file).
Say for instance I have a button on this custom view, that when pressed, simply deletes the image and takes me back to the camera view to take another image. Can I handle the IBActions for this custom view within the ViewController for my camera view? Is this bad practice?
Any guidance on how best to implement this would be really appreciated! Thanks.
I would not suggest putting the button on your custom view.
I would have the UIViewController display the custom view and also give display a button for your action. Most likely the UIViewController will want to display a UIToolBar at the bottom of the screen which will allow for multiple buttons/actions, but that's up to you.
But why do I say this? Compartmentalization. Your custom view has no need or use for the button. It's meaningless to what your doing... displaying the image. Your custom view will also probably be used in many locations, several of which won't want this button displayed. Even if your custom view had the button it wouldn't know what to do if someone tapped it. It would then have to pass that interaction off the view controller which cares about the action and and handle it. Your custom view will mostly likely have public methods allowing other code to give it directions (like clear or undo).
Depending on the say things go, you may decide you want a custom UIViewController which handles interactions on your custom view. Then any other view controllers could just add it in as a containerized view controller and you could have the same functionality with no code duplication at several places in your applications.

Do I need a ViewController container or a composite view?

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

iOS - relations between views

I'm just learning the iOS, so my question is very basic... I've read a lot about organizing subviews in the application, but there are so many things there, that I would like to ask you if I've understood it well...
The main part of the app is a window. ViewController manages only one view. In a window I can set the rootViewController. This controller manages the view during entire application workflow. Next I can create some subviews, connect these subviews to the main view (parent) using outlets, and the when instatiating rootViewController I can add my subviews by :addSubview method. Am I right more or less?
And one question more... Should each subview be managed by a dedicated ViewController (then, the parent has outlets to these controllers) or I can change the subviews state directly from parent ViewController?
And short example:
I would like to create an iPad app which has (both visible at a time):
- at the top: short form and button (user enters some data and clicks "Save" button)
- at the bottom: a table displaying provided values
So:
I can create one main view, and two subviews (for form and table). Each time I add some values table will be refreshed using the parent controller... Does it make sense?
It you see that I understand something wrong, please tell me what should I read about.
Thanks for patience.
iOS follows MVC pattern.
The controller class is a manager which binds data to the view. So you can have separate classes for your view and data.
Your understanding is right. To achieve the things you have mentioned,
Create a subclass of UIViewController.
Add two subviews to it (TableView and Button). This could be done using xib or programmatically
Add the delegate methods of your tableview inside your controller class and set tableview's delegate as your controller class.
Add the event for button.
.
rootViewController is the starting point for your application and you can create more viewController and add subviews on the viewController depending on your needs for application.
I would like to create an iPad app which has (both visible at a time): - at the top: short form and button (user enters some data and clicks "Save" button) - at the bottom: a table displaying provided values
you can create UITableView & UIButton as subView to the UiViewController(will be Owner of the subviews) or any other subviews like labels,textfields etc.
The subviews are connected to the files owner that is the viewcontroller..not the parentview.

Resources