Swift Container control from parent view - ios

I have two views, one is a main view, and another is a container view. What I wish to do is send a variable to the child and for it to execute my function. How do I tell the child view these two things from the parent view?
A few problems I have had is, ViewDidLoad does not work in container view. and when I tried to segue the information it also said that a periotical programming or container has been implemented indicating to me that the container can not be segued.
What I am trying to do is have two tables, the first table has a list, and the second table changes depending what you select in the first table. So I decided to seperate the two tables using a container view which is working for the most part.

First of all, you should note that any containers you create will be available through the childViewControllers property on your main controller. This gives you a link between the main controller and the child controller.
Now what you are trying to do is to change something in the child's table if the parent's table changes. There are many ways to do that, but in this case there is a pretty simple technique: you always know when the parent's table cell selection changes, in didSelectRowAtIndexPath. So what you need to do is simply within didSelectRowAtIndexPath, when the row changes you call a method in the child controller that passes in whatever information about the currently selected row you want to use. That method will change the table and do whatever else you want to do within the child view, since it's part of the child controller.
Using delegates or KVO or any other technique is overkill and bound to make the code much less readable.

You can use delegates to do that. Delegates are just protocols you can implement to pass data to another view:
protocol nameOfProtocol {
func someFunc
}
You can search for a tutorial or examples easily, that way you can visualize it much better than just looking at some code here.
If you want viewDidLoad to work you can create a view in storyboard, give it an identifier name (and also setting it to the correct view controller) and you can declare it like:
let viewController = storyboard?.instantiateViewControllerWithIdentifier("viewControllerName") as! ViewControllerName

Related

Access textField.text variables from different view controllers

I'm creating a login page with multiple view controllers and at the end of all the view controllers there will be a create account button. I want to be able to access all of the textField.text variables from every view controller. I tried to use core data and structs. However, xCode wouldn't compile it and would spit errors. Here is a ScreenShot of all the view controllers I need to pull data from: http://prntscr.com/lqt9b4
"I want to be able to access all of the textField.text"
Do not do that. You should treat a view controller's views as private. You should create a model object (a class) and have each view controller change the relevant field(s) of the model object.
Alternately you can use a struct and pass a new copy each time it changes (since structs are value types.)
Maybe reconsider how to do this. A sequence of VCs like this would require passing each part of the puzzle onto the next. If you want four VCs to work together, it maybe better to use a UIPageViewController-style arrangement, with the overall view controller then pulling data from each sub-VC.

How to implement two similar views efficiently in UISegmentedControl

I've two exactly similar views which I show in a two segmented control. Refer to image below. The differences between these two views is the parameter which I send to backend to fetch the values and the title. Even the returned values are same.
I've referred to some tutorial which cycles from one view to another when segment is selected .
I've ended up with two files with exactly same code. How to optimise this implementation so that I can implement with one piece of code only.
The two contained VCs have exactly same code to fetch values from backend and display. I've only one function which I've used in both VCs to fetch but there are other code sections such as Tableview delegations and other codes which are common to both.
In storyboard both are duplicate as well.
Is there anyway I can make it more efficient?
This could be a case for making your two view controllers be subclasses of a common superclass.
Or it could be even simpler: make them two instances of the same view controller class, which knows what to do because you pass a parameter at creation time telling it what to do.
For example, my Albumen app uses four view controllers, which differ primarily just in what query they perform on the user's music library. So I've elected to make them four instances of one view controller class, with an enum property saying which query it is, and any other varying functionality determined through switch statements on that enum.
I think you need to create only 1 VC ( In IB and code ) , put all the logic inside it and either
1- Add once instance / container of it to the MainVC and manage the process of selecting a segment to reload the content ( Recommended )
2- Add 2 instances of it to the MainVC and manage hide/show when the segment is selected

Storyboards: How do I use the same view controller in several places?

For years, I've hand-coded my view code for iPhone apps, but now I'm giving storyboards another look.
One common pattern in my code is to use the same view controller in two places, but with slight UI variations. For example, when browsing a list of brands (BrandListController), I'd like to show a table view of all brands in the system; tapping a brand shows you its products. But when filtering items by brand, I'd like to show a table view of brands (with the same content and same cell appearance), but I'd like tapping a row to take you back to the filter screen instead of showing you that brand's items. I'd also like a "Search" bar button item in the top right.
It's easy to make these things happen in code, by just adding a boolean member variable so the controller can be configured before it's presented.
But how would I do this with storyboards? I could have multiple controllers segue to the same instance of BrandListController, but again, I would want the controller to have different behavior and include/exclude UI elements based on how it's used. It seems like a bad idea to create two separate instances of BrandListController in the storyboard, because then I would have to duplicate all the outlet connections and I would have to keep changes in sync. But what are my other options?
The thing to realise with Storyboards is that you don't necessarily have to only use a single storyboard.
You can use multiple storyboards or use them in conjunction with nibs etc...
However, in this case what you could do is still use you boolean property on the controller.
Then in the prepareForSegue method of the other controllers you can set this boolean property to change the behaviour. You might even have a couple of nibs that defines a small section of UI to place into the view depending on the property.
I've done stuff like this to pass blocks into view controller too.
For example...
I had a "User Search" controller that had a default behaviour of if you tap a user it will push to that user's profile page.
But I could pass in a code block that would, for instance, dismiss the search controller and I use the selected user to create a new message to them (or whatever). Or something else entirely depending on the code block I passed in.
EDIT
LOL, just re-read your question. What I did with the blocks would work for you too. I created a block property called userTappedBlock or something. If that exists then I run it when the cell is tapped. If not I do the default behaviour.

iOS Container ViewController data flow

My objective is to show dealer locations in two different ways: a map and a tableview.
I have a container view controller (DealersViewController) which contains two child view controllers: DealersMapViewController and DealersListViewController. The user can switch between the VCs with a UISegmentedControl placed on the navigation bar. Tapping on a map annotation or a tableview cell will push a DealersDetailViewController.
The switching is already implemented (using code from Changing view controller when Segmented Control changes) and seems to work fine, as does the pushing of the detail.
What I would like to improve is the flow of data between container and children. The dealer locations are downloaded (JSON) from the internet in the parent and on completion an NSArray *locations property is set on both the map VC and the list VC. This array will contain dictionary objects created automatically by AFNetworking, each with location data (each location dictionary will have a title, subtitle, latitude, longitude to conform to MKAnnotation protocol, but also other things like image and description etc).
My question is: How can I be sure that the container VC and both child VCs 'agree' on how location data is structured? Theoretically, if someone wanted to develop another child view controller to add to my container that shows dealer locations in a collection view for example, how can he formally know how to expect data.
Apple says: "If the container needs the child to declare methods or properties, it should define a protocol to enforce this:". I could force the children to declare the locations property but the array could contain anything…
Maybe the parent could be a datasource for the children? I haven't tried this approach yet.
I am probably overcomplicating things but my objective is also to learn how to properly create reusable components and also practice using stuff like custom protocols / delegates and design patterns in general.
Thanks.
If I understand correctly, your issue is structuring data so that all of your controllers have the same understanding of it.
Probably the best way to go around it is to create a custom location class, and have the JSON deserialize into an instance of that class and then just pass it around as you see fit. There's quite a few ways how to go around deserializing, but JSON Model is a nice example of how to handle it automatically.
Tl;dr: convert your JSON dictionaries to custom classes and then pass them to your child view controllers, via properties or delegates, whichever you find more convenient.

Connecting a UIView to a UIViewController

I have a UIView subclass which contains some labels, a tableview, and a few other bits an pieces. It is currently the delegate and datasource for the tableview, and also manages many UI actions, none of which rely on data. For example, when an 'edit' button is pressed, it knows how to update its controls, but it won't do anything when 'save' is pressed besides switch the controls back to the previous state. All of this is done in code, I'm not using IB at all in this application.
I now want to plumb in all the data model changes that it can provoke. But I would like to put these in a new controller class, which I guess is the MVC compliant way to do things. I'm not sure how to get there.
First, I need to create a custom controller class. Should I be exposing from the UIView subclass a few of the controls so that the view controller can access them? For example, I will need to read and write to a textfield in the view, so should I provide a getter/setter for this?
Secondly, the tableview - instead of the UIView being the delegate, should I expose this also, and make the view controller the delegate? I.e. view.tableView.delegate = self from the UIViewController?
And finally, how do I launch the view from another view? Specifically, this is a paged scrollview application similar to the weather app, so I have a mainView UIView that specifies the single paged scrollview and then adds multiple custom UIViews, one for each page. How do I replace [scrollView addSubview:myCustomView] and instead add the viewController? And how do I connect the view to it's controller and vice versa?
I've not tried all of this without IB before so thanks for helping.
Your question is very broad, and part of the answer would depend on how you code your solution. I will try replying with a few hints of what works for me:
View: As a general rule of thumb, keep in mind that a view object should be something very generic, that knows nothing about other views outside of its own hierarchy. As such, a view should not rely on any specific interaction with other views, but rather communicate back to its delegate / owner / creator through callbacks, protocols, blocks, etc, when needed.
View Controller: Any time you need to make two views in different hierarchies interact with one another, my suggestion is that you stick to handling that interaction through the view controller. By doing so, you'd be making sure your view is not contaminated by code that would be useless in a different screen.
Also please keep in mind that UIViewController for iOS is intended to be a class that you use for handling the complete visible view hierarchy, as opposed to acting as the controller for a single view. As such, I recommend that you don't attempt have a controller for each view, but rather a single one to handle them all.
Publishing view elements: How much a UIView exposes as public in its header file is up to your implementation. Any method that handles the way the view looks, that looks to be generic and reusable, and that doesn't need anything from outside the scope of the view's tree, is surely something you want to include in it's implementation and publish in the header file.
The same goes for any property that you feel is highly probable that someone from the outside will need to access.
Suggestion: publish only what's really needed. Usually publishing new methods and properties is easier than removing them later on.

Resources