OOP - Using a UIView to coordinate multiple subviews? - ios

This is an Object Oriented Programming question:
So I am trying to build a UIView class that displays scatter plot. In my current implementation, I've created a datasource protocol that allows the chartView to ask for all the info it needs to plot the its data.
As it stands right now, when someone initializes the chartView and gives it a datasource, the chartview creates/manages several subviews: a 'dotsView' that displays all the data points, a scrollview to which the dotview is added (so it is scrollable), and a 'skeletonView' that sits in the background and displays other chart data like grid lines.
This system at first worked great, however, I decided that i'd like to animate changes to the points, and so i began to contemplate using a collectionView in lieu of the 'dotsView' placed within the scrollview since it'll handle the animation for me. However, as a collectionview would require a delegate, datasource, layout object, etc, all the sudden my chartView seems to looks more and more like a controller and not a view.
Now here is my question: Is it the wrong approach to allow a UIView to coordinate/configure other UIViews, even if those UIViews are a fundamental requirement of the whole? On the one hand, I'd love to preserve the simplicity of my chartView's public interface (initialize the view, give it a datasource, and you're done). On the other hand, this chartView is really not a view anymore, its more like a controller. But I don't want a consumer of my chart to think/treat it like a controller, I want them to use it as a view.
Any thoughts? I'd love to hear the insights of others.
Thanks!

It is totally fine for your ChartView to create a UICollectionView, use it as a subview, and be the data source and delegate for that subview, because the use of UICollectionView is an implementation detail of the ChartView.
Apple does this in UIPickerView. Under the covers, a picker view creates one table view for each component, and the picker view makes itself the data source and delegate for each table view. You can see in UIPickerView.h that it conforms to UITableViewDataSource. You can check that it conforms to UITableViewDelegate at runtime with +[NSObject conformsToProtocol:], or by using class-dump on the UIKit framework. Or you can just write a test app and poke around the view hierarchy. The debugger command po [[UIApp keyWindow] recursiveDescription] will get you started.
UIPickerView is the only view subclass in the iOS SDK that I know of that acts as the data source and delegate for its subviews, but many other UIKit view classes create and manage their own subviews. Examples:
UIScrollView has private subviews for its scroll indicators.
UITableView has private header, footer, section index, and row separator subviews.
UIButton has a private UILabel to display its text and a private UIImageView to display its image.
UISegmentedControl has private UILabel and UIImageView subviews.
UIProgressView uses several private UIImageView subviews to display its parts.
UISlider uses several private UIImageView subviews to display its parts.
UITextField uses private UIImageView subviews.

You answered you own question my friend: Is it the wrong approach to allow a UIView to coordinate/configure other UIViews -- YES!. Views should be casted by a Controller from an organizational stand point IMHO. I would build a Charting Controller that can cast out single and composite views and kill two birds with one stone. The you could route urls to the controller from Ajax to change the data represented in the chart

Related

Create a custom scrollable collection view that mimics the behaviour of UITableView in Swift

I have this task that I need to create a custom scrollable view with 3 different types of cells from scratch.(no UICollectionView nor UITableView)
I have no idea what is the best way to start. Wether I should subclass UIScrollview or ...
Any guidance or direction would be highly appreciated.
Create object of UIView, keep adding in UIScrollView depends on your array count.
Keep dynamic calculation for next UIView add subview in UIScrollView
Put transparent UIButton on UIView or use touch gesture to implement like didSelectedRowAtindex.
Another solution we can adapt when there is no UITableView.
Both TableView and Collection View inherits from UIScrollView. So using the parent class could be efficient. But inheritence also serves independent extensions it would also be ok to use the sub classes.
So, Decision depends on what you do. Here in your case.
If one of the cells include a text field for user entry, then scrollview could do better as it offers convienience to scroll/shrink/retain the current UI while showing all the content of UI even when keyboard is present.
If the cells only involve fields like labels,switches,indicators etc then tableview is the choice.
If the cells has non-consistent or non free flow sections then collection view could be better.

Custom TableView iOS - General questions

This is more of a general question. I want to create a scene where the top 1/3 of the scene is say a slider with some text labels, and then the rest 2/3rds of the scene is a data table of recorded values of the above slider(user moves the slider to the correct value, hits 'enter', and the recorded value is showed in the data table below). I assume this is a modified table view, but I'm not sure? Can anyone point me in the right direction on how to go about doing this? Im not quite sure where to begin looking up information/tutorials on this type of layout. Any help would be appreciated!! Thanks so much!
It isn't a "modified table view". It's a table view. There's no problem here; you have a scene with a UISlider, some UILabels, and a UITableView. There is nothing to "look up". No law says that a UITableView has to occupy the entire scene interface - though of course in that case you can't use a UITableViewController, but that's no restriction at all. Just set your table view's delegate and data source to the view controller that owns the scene.
You'll want to create a UIViewController that contains the UISlider and a UITableView within it's xib file. Hook the view elements to its ViewController.h, and set your ViewController as a UITableViewDataSource and UITableViewDelegate.
In ViewController.m, fetch the data follow the UITableView protocols to load it into cells. Then, when you would like to refresh data call
[myTableView reloadData];
Apple's UITableViewDelegate Protocol
Apple's UITableViewDataSource Protocol

Where to add subviews in UIScrollView

Is there some "best-practice" way to add subviews to a UIScrollView?
For Example:
I have a UIViewController which loads images with corresponding description from a server.
Those images+descriptions should be added in a horizontal scrollView.
When the data is loaded, should I create a method in my UIView to handle this stuff,
or is it more convenient to do this in my UIViewController?
Your view controller would be an most appropriate place to handle this, as controllers should connect your view (the scroll view) to the data (the images).
If the scroll view's layout is simple, it could be done entirely with the controller. But, if the layout is complex, you may want to consider subclassing UIScrollView and handling some of the layout there (similar to how UITableView works).
For more info on standard application architecture, read Concepts in Objective-C Programming on Apple's developer site.
By my way of looking at it, the separation of concerns would break down like this:
the UIViewController is responsible for getting the images and handing them to the UIView
UIView is responsible for displaying them.
So the -addSubview: is a view implementation detail, should go in the view, and be opaque to the controller.
There is plenty of opinion that both UIViewController and UIView are confused and intertwined in such a way to make them both part of the conceptual "view" (in a MVC sense), but I think it's still cleaner this way.
As you can see, opinions differ. :) Personally, I despair of MVC, and think Model-View-ViewModel to be a much clearer, cleaner, and more sensible way of approaching all this.
UICollectionView is same as that of UITableView except it is meant to display Images and its description.
Here is what you can do.
Create a UICollectionView, it is the subclass of UIScrollView. SO there is no need of UIScrollview.
Since you need image and description both for each item, I will recommend delete the UICollectionViewItem from UICollectionView.
Create a seperate custom UICollectinViewItem class, define UICollectionItem in .xib file (UIImageVIew and UILabel).
When you define the datasource method "– collectionView:cellForItemAtIndexPath:" define the UICollectionVIewItem class here. Exactly we defines custom UITableVIewCell.

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

Embedding a UIScrollView with a UITableView

So Path uses this type of page where there is a view above their customized looking table that is a background photo, which contains some user info among other things. I'm trying to recreate something very similar to this.
So lets say that I hypothetically wanted to make a view that shows exactly the way the Path app does, but instead of that weird customized version of a table view that they have, there is an actual table. How would I do something like this? The reason why I would need there to be another UIScrollView embedded into the view is because the entire thing needs the capability to scroll. I'm trying to be as detailed as possible, but its a little difficult to explain.
What I'm imagining is going to happen if I just tried it right now, is that I'd embed a UIView above a UITableView within a UIScrollView that's the size of the frame, and when I'd go to scroll, the user would only scroll the UITableView, and not the entire thing at once. Hopefully that helps convey my doubts.
Another possibility is that I'm totally over thinking this, and I can simply just subclass a view in the header of a UITableView and it would stretch the width and height that I'd like. Hopefully this is the way as this would be easy!
Anyways, can anybody weigh in on this?
Path just uses a normal UITableView with UITableViewStyleGrouped.
The custom view at the top is the header of the first section of the table.
They also access the UIScrollViewDelegate method of the UITableView to change the look of the view (I think the image is moved) when the scroll view scrolls.
If you'd like a tableview that only scrolls within a part of the view and other stuff above it then you need to use a UIViewController. Then you can make it conform to UITableViewDelegate and UITableViewDatasource and add a UITableView and make the view controller the datasource and delegate.
Then you can also add a UIScrollView to it as well.

Resources