How to pass a reference to UIView instance - ios

I have a set of "controls" in a UIView that are displayed inside a UITableViewCell - this includes a UILabel, and some UIButtons. When a UITableViewCell is pressed, I'm displaying a new view from a different UIViewController. I want this view to include the "controls" from the UITableViewCell with the buttons/label in the exact same state as before.
What's the correct way to do this? Should I create a model that stores the state of the buttons/label and then access the model or is there an easier way?
Many thanks :)

If you need that for beautiful transition animation only, it would be better to take a "screenshot" of your UITableViewCell. But if they should be interactive as well, just move them to new superview. But you will need to maintain constraints/frames/outlets consistency in both places...

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.

MVC pattern controller responsibilities and best practice when presenting a view and transitioning through states

I am familiar with the concept of MVC in which we divide the concerns of modeling, presentation and processing of information. But when it comes to a real life example it gets hazy.
Lets take for example Apples UITableView. Say we have a coresponding controller which takes care of suplementing the table (the presented UIView is custom and just has a UITableView, exposed as a property, at the moment).
The UITableView has a property backgroundView which I want to use for displaying some info when there are no elements to display. The real question is where should it be suplemented?
Make a method in the custom view which creates the view and shows it (showEmptyTableInfoViewWithMessage:).
As in first example but just expose an UILabel as a property and make a simple hide/show method and work on the labels text property from the controller.
Create a custom UIView which will expose the UILabel. Alocate it and assign it to the backgroundView property in the controller.
Create a UIView with an UILabel rigt in the controller and assign it to the backgroundView.
As all of these examples will work I am wondering which one is the proper way (the best seperate of concerns / maintable way). I belive No. 4 is the worst but that is just my feeling at the moment.
Thank you in advance for any information on the best architectural design/approach.
A UIView should be responsible for hiding or showing its subviews and managing its subviews. It shouldn't be responsible for whether or not itself is visible. That's why it exposes the hidden property--so outsiders can do this.
I don't like any of your four options personally.
I'd go with one of these two:
The backgroundView will already have a view object there. We can just create a UILabel object and add it as a subview to the table view's default backgroundView and add the appropriate auto-layout constraints. This would probably best be done by subclassing UITableView, and if so, I wouldn't expose a UILabel property, but rather expose an NSString property whose setter simply sets the label's text, and whose getter returns this text. You may expose a few other methods perhaps for setting the label's font and a few other things.
Create a subclass of UIView, perhaps called UIBackgroundView. This would be a UIView with a UILabel (and whatever else setup you want on it). It shouldn't expose the label directly, but like before, it should instead expose properties that let you set the things about the label you might like to set and does it via proxy. Then you instantiate it with a factory method something like this:
vwBackground = [UIBackgroundView backgroundViewWithText:#"Hello World];
And then simply:
tableview.backgroundView = vwBackground;
Between the two options, which you use depends on what level of reusability you want.
Option one is probably slightly better, and it saves some coding after you've created the subclass, but obviously, you can only do this with table views. If you want to do the same with a UICollectionView, or a UIScrollView, or a UIImageView, or whatever you can find that has a backgroundView property, you'd have to create similar subclasses for each... but in the end, it'd be easier and more intuitive to use, I feel.
But with option two, you can then automatically use your UIBackgroundView anywhere. It's just a UIView with a label, and you can do with it anything you'd do with any other UIView object.

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.

How could I clone/duplicate some sort of UIView for iOS?

(screenshot below helps explain what I am trying to do)
The idea behind this is that I have a UIView, with various different UI elements inside, for example, let's say I have a UIView, and inside there we have a UILabel.
Now I'm wanting to duplicate the UIView (with the label inside) BUT somehow after that I need to perhaps make a change to the label, e.g. change the text property.
The reason I need something like this is so I can structure the UIView with everything I need in it looking nice, but to actually have different data with different copies of it.
I'm not certain this is the best approach, but it's the only one I could come up with. If anyone has any ideas on how to do this, or any ideas on a better approach I'd really appreciate it. A lot!
I personally think the best answer is to create each view separately and configure it as needed. You can make a method that just configures new UIViews to look the same, and pass each view through it.
However, if you really need to copy a UIView, you can archive it, and then unarchive it:
id copyOfView =
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:originalView]];
UIView *myView = (UIView *)copyOfView;
[self.view addSubview:myView];
If you have a bunch of these, make sure you're using the Instruments time profiler to check your drawing efficiency.
This is a very natural and useful thing to do. What you're looking for is a container view controller. Put your reusable "cell" into its own view controller and its own nib file. Then, in your parent view controller, use addChildViewController: to add as many of these as you'd like and configure each of them. They can each have their own IBOutlets that you can use to modify the contents.
This is very similar to the pattern used by UITableView and UITableViewCell (it doesn't use "child view controllers" specifically, but it does use this pattern).
For full details, see "Creating Custom Container View Controllers" in the View Controller Programming Guide for iOS.
Note that Storyboard includes a "Container View" as an option in the object templates to make this even easier.
If you want lower-level access, you can also do this by hand using UINib to load the nib file and wire its outlets (and this is how we used to do it before iOS 5), but today I would use child view controllers.
If you have only one label inside it the obvious solution is to have a custom UIView subclass with that label added as a subview. Everytime you need a new view you make an instance of your custom subclass and set the label text. If you have multiple things to set, some of which are common to all your custom subclass views you can use the prototype design pattern, it's pretty straight forward to implement.

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

Resources