View Controllers and Multiple Views - ios

I'm working on my first iOS app and am trying to understand something about Views and View Controllers.
My question is this: In an App like Instagram there's an 'Activity' tab in the main Tab Bar Controller. The activity tab has a UISegmentedControl for "Following" & "You" which display similar data, but query different records. Would the data in each of these UISegments be controlled by a separate controller? (FollowingController and YouController, for example).
What about instances like viewing locations on a Map, and you want to have a Map view and a List view? Would there be a MapViewController and a ListViewController, or would one View Controller manage all of this, and different views would be loaded conditionally based on what the user selects?

No, you could use a single UIViewController and/or UITableView (depending on how you would like to present your data) and just change the dataSource based on Segmented Control's option.
For more information, please check UITableViewDataSource for instance. In case of Table View, dataSource is nothing else than an array of some data.
Another approach besides Table View / Collection View would be to put Container View in UIViewController which would use just a single UIViewController instance. For more information refer to the documentation. Especially, take a look at the picture:
For your second question - no again. You can have a single UIViewController and place instances of MapKit and/or list (aka UITableView). You can do that in Storyboard by dragging an instance of MapKit like this:
And your single UIViewController might look like this:

Sounds like inheritance to the rescue here.
If you have a UISegmentedControl for "Following" and another UISegmentedControl for "You" then it there is the possibility that the best architecture will be to use inheritance and have two separate controllers for each of those UISegmentedControls, with names FollowingSegmentedViewController and YouSegmentedViewController, this way your separate controllers know the type of data they are loading and working with ("You" data or "Following" data) and other special considerations or differences between your "You" UIView and your "Following UIView like one being a map and one being a table.
And then for common UISegmentedControl functions and properties you have a base class that both your FollowingSegmentedViewController and YouSegmentedViewController inherit from, call it BaseSegmentedViewController or whatever is appropriate for your app and archiecture.
This inheritance allows you to share common UI elements (via #outlets) and other methods/functions between FollowingSegmentedViewController and YouSegmentedViewController but then also address differences between the two specifically in their distinct controllers.

Related

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.

Best Practice: UIViewController or UIView

I am gonna design a component in IOS, in which we will have Table view and Grid View; means user can see his data in table or grid. So what i am doing is i added a UIViewController and added two child view controller one for table and another one for collection view. I am handling everything using UIViewController only. Its means when user wants to use my component he has to add as a child view controller only. My question is that "Is it the best practice to use UIViewController like i am doing or Should I convert everything to UIView because UIView is light weight." I am gonna write only presentation logic in my component. We will get data from outside using delegate. And if i should use UIView then when should i use UIViewController?
Thanks
Your current approach is correct.
UIViews should do one and only one thing: paint a view when asked to.
UIViewControllers are more complex. They are are responsible for setting up views with any data they need to do their job, compositing multiple views (or view controllers) together if needed, responding to events from view components or from the device in general, and communicating with the rest of the code/system.
Because your code wants to show two different kinds of information, it fits the UIViewController much better than the plain UIView style.
As you've pointed out, Apple themselves have many examples of UIView subclasses that have delegates and do complex things. However, if you're writing a new component and it is complex (as yours is), I seriously recommend going for the UIViewController approach.
A note on history: Apple used to be of the advice that UIViewControllers should only show/composit UIViews and not other UIViewControllers (even though, confusingly, they didn't always follow their own advice!). This would align with their making of some quite complex UIView subclasses. However, they changed this stance a while back, and added support to UIViewControllers for compositing other UIViewControllers' views inside them. If Apple's stance had always been as it is now, you might find that some of their UIView subclasses were implemented as UIViewControllers!
As an experiment, it would probably be quite educational to try and implement your component both ways. I predict that you'd find UIView approach more unwieldy, with you having manually re-plumb some of the 'wiring' that you'd get 'for free' with the UIViewController approach.
Avoid putting logic in UIView subclass.
As I think you can make grid view by using table view just simply add multiple views on each cells
at time of switching grid to list or list to grid simply check your type and reload tableview

How to add multiple instances of custom subviews in UIViewController

Often, when I'm making my apps, I'm in this situation : I have a UINavigationController, handling the view stack, some UIViewControllers, controlling their respective views...
But when I want to add several custom UIViews in my mainView, I don't know how to manage my code.
Each UIViewController needs to handle one and only one view (wich normally occupy all the screen size), and a view should not control their content (update it a the extrême limit).
You can't neither do this :
[myViewController1.view addSubview:childViewController.view];
So if I want to achieve something like this, what should I do ?
The orange parts have to be 3 instances of the same UIView(Controller?), but with a content depending of a NSObject (User, obviously).
I think this very important to segment your content, this should be an easy problem, but I found a lot of contradictory answers so, what's the best practice to handle this common issue?
Theses orange views should be instances of UIViewControllers in order for it to handle their UITableViewDatasource? Is addChildViewController relevant in this case?
I already found a lot of things which work, but I don't know what should I do...
Also, I'm using xibs.
Thanks in advance if you can help me (and other people I think).
You can do it either way (view or view controller) depending on how you want to handle things. Certainly, you can have one object be the data source for multiple tables, so in that case, you would just add multiple views. If, however, you want to keep your code more compartmentalized, then add view controllers, and have each control its own view -- to do this, you do need to use addChildViewController, and use the methods that Apple describes for creating custom container controllers. Alternatively, you can use container views in a storyboard which makes the process of creating custom container controllers simpler.
You're on the right path... Create separate instances of your subviews, and add them to your view. If you will have more than 3 (for instance, imagine coverview for your music, and you could scroll indefinitely left and right), I'd take a look at UICollectionViewController ... That will help manage cell re-use.
But, if it's just 3, just create three instances with different frames and add them to your view.
Here's how I'd do it:
each orange box will be a custom view (inherits from UIView)
the view will have the label, image and the tableview.
since you are not sure of the number of instances of these views you'd be using, its better to use some kind of tagging, so that you can have one place for the datasource and delegate methods of the tables in these orange views.
in the datasource and the delegate methods, you can make use of the tableView.tag (same as the orangeView.tag property).
I personally dislike having more than one viewController in a view (except the splitVC), probably because I haven't had a such requirement.
I dont see how a uiviewcontroller for orange box would help, over a uiview.
as #James Boutcher mentioned in his answer, UICollectionViews will simplify this issue further.
Why not creating a UIView class and overriding the drawRect method and then adding subView for this class in your myViewController1.view

Trouble understanding viewControllers in iOS

I'm new to obj-c/iOS and I'm having trouble understanding conceptually at least viewControllers. I've read a lot of the Apple Doc's, I've even used viewControllers to some extent in xCode, but I still don't quite get what they are, or what are the best ways to use them.
I've been an AS3 dev for many years so my mind works in the context of MovieClips/Sprites and the Display list to get graphics on the screen.
Ok so from my understanding...
A viewController is a kind of class that handles graphics in some
fashion and then allows you to do something with them?? What is it in it's most basic sense?
You seem to add viewControllers to a Window class, which I guess is a bit like
adding a display Object to the Display list?
What is it that a viewController does for you in it's most basic sense?
Are there certain things you definitely can't do with them or shouldn't do
with them?
Do viewControllers need to be connected in some way to the rest of the iOS framework to function (apart from being added to a window).
How exactly do they use data? (I've read up on MVC, I understand that conceptually this is a slightly different question) as I understand it you don't hardcode data into a viewController, so how does a viewController access any static data?
Let's say I just wanted to throw an image up on the screen, exactly what part would the viewController play in that process? is it just something which handles only one small aspect of that process or is it the whole show and handles everything?
Does one viewController handle multiple images? is it like it's term, a "controller" for all the images presented on screen, or does it handle one image at a time?
What is a viewControllers connection to the image(s) it handles? it contains references to them?
I'm using the Sparrow framework which is helping but I would still like to be able to get my head around what viewControllers are so I know how to use them properly.
Ha, I apologise for the above I know it must look like I'm completely confused :) thanks for any advice.
Hope this helps you:
A viewController is a kind of class that handles graphics in some fashion and then allows you to do something with them??
It's the glue between a View (Xib File) and the Data (Could be
CoreData or whatever you're using in the backend). All the UI Elements
you are using in the View you normally define as properties in the
controller to get access to them.
What is it in it's most basic sense?
You seem to add viewControllers to a Window class, which I guess is a bit like adding a display Object to the Display list?
I don't really know AS3 so I cannot compare Display lists with ViewControllers. But basically ViewControllers are there to handle
different types of transitions between the views and accessing
(setting/reading) the data which is displayed in the view.
What is it that a viewController does for you in it's most basic sense?
Like I've written above. Most basic sense they interpret what the user
does on the view and depending on the action of the user changes the
model.
Are there certain things you definitely can't do with them or shouldn't do with them?
It is always hard to keep the border between model and controller.
They are pretty close to each other. So what I normally try is to
delocate all logic stuff (like calculations, database access and so
on) this does more belong into the model part. But of couse you're
using these external classes in the controller.
Do viewControllers need to be connected in some way to the rest of the iOS framework to function (apart from being added to a window).
Well like you already have written the ViewController needs to be
connected to a view. Otherwise it would not make much sense. There are
different subtypes of UIViewController such as UINavigationController
where you probably need to overwrite some other methods to provide the
whole functionality wanted by these special subtypes.
How exactly do they use data? (I've read up on MVC, I understand that conceptually this is a slightly different question) as I understand it you don't hardcode data into a viewController, so how does a viewController access any static data?
There could be different approaches to store the data. Simplest way
would be to have the data directly stored in the UIViewController.
This could be a custom class which is the container of the data. All
changes are directly written into this class and displayed by the
UIViewController. But in most of the cases it makes sense to use
CoreData (Which is responsible for reading/writing the data into a
sqlite database). You could look at CoreData as your model and the
UIViewController gets the data from there and passes the data which
the UIViewController has received from the View back to it.
Let's say I just wanted to throw an image up on the screen, exactly what part would the viewController play in that process? is it just something which handles only one small aspect of that process or is it the whole show and handles everything?
The UIViewController would store an internal Property (UIImageView *)
which is in the Interface Builder connected with the UIImageView you
have created in the Xib file. So over these property you can change
through your Controller the image.
Does one viewController handle multiple images? is it like it's term, a "controller" for all the images presented on screen, or does it handle one image at a time?
Yes, this isn't a big problem. You can have as many images you want.
You just need to have the properties defined in the UIViewController
and linked to the View.
What is a viewControllers connection to the image(s) it handles? it contains references to them?
Yeah, its like a reference to the UIElement. You can then change
whatever property of the UIImageView you want directly from the
UIViewController
Some useful links:
Apple Official ViewController Guide
Apple Official ViewController Basics
You should have a look at Storyboards (U can use them since IOS 5.0)
I recommend you to check:
https://stackoverflow.com/questions/1939/how-to-articles-for-iphone-development-and-objective-c
Here are the answers to your questions:
No, it's doesn't handle graphics. It's the controller of the MVC design pattern. It handles the lifecycle of it's contents (for instance the views) and the data linked with.
A UIViewController is set as a root of an UIWindow. For instance, a UINavigationController is a subclass of UIViewController that stacks UIViewController in order to deal with the navigation.
Response in (1)
Try to be more specific with this question please.
As already commented, it's useful if you use the already built-in components like UINavigationController or UITabBarController.
For instance, you can have the data in instance variables and the display them in the contained UIView.
The UIView attached to your UIViewController will contain an UIImageView. Your UIViewController would have a connection with it in order to whatever changes you need, for instance, changing the image when the user press a button.
It can contain multiple UIViewsand therefore multiple UIImageViews (it's a subclass of UIView)
As commented, they would be contained on an UIImageView and would be linked programmatically or with an IBOutlet.
In a nutshell, a view controller is the controller in the MVC pattern. Please check this link before reading further so you're up to date with this pattern:
http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
OK, basically a controller manages a collection of views. It also fetches data from your model and sets the state of the views. It's important to note that the views know nothing of your model (your data), and the model knows nothing about your views. A controller also receives events from the views and decides how to change your model accordingly. It is essentially managing the synchronisation between your views and model.
There are technologies that help automate this such as KVO and key value binding. A google search will help you there.
One more thing. No other part of your application should access your views except for the controller. So generally in an application controllers tend to communicate with each other, for example via transitions or the delegate patterns between controllers under a navigation controller. So your application backbone tends to be controllers talking to each other.

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