How can I clone a UITableView from one controller to another so it stays in synch? - ios

I found this in SO; it doesn't exactly answer my question, which is: is there a way to clone a UITableView from one controller to another while using Storyboards and maintain synchronization?

You can clone them in the sense that their initial property values remain the same, like position, layout etc. For this, just copy the UITableView from storyboard, go to destination view controller and paste it there.
If you share same UITableView object between two view controllers, it is still possible, but you must estimate how much work you would have to do yourself. When a view controller solely handles a table view, much of the work is done under the hood and table is handed over to you. In case of your UITableView shared between two view controllers, you would have to play with it quite carefully. You need to take care of entire life cycle of the view - see the usual methods like viewDidLoad, viewDidAppear and so on. How would you take care of them when your view exists in two scenes? Maybe you would be inventing a unique design pattern - if at all you find the most optimistic and programmatically correct way to accomplish it.
With storyboards, you cannot achieve cloning up to the level wherein data changes will reflect seamlessly between the two. Storyboard is, as the name suggest, just a board, where you can draw things to know how would they look initially, before your code takes over.
In order to achieve what you want, you have to create a shared model that updates two table views through proper delegate methods. Most likely such a model (NSArray, or any such collections as per your requirement) can reside inside a shared class (app delegate isn't a wrong choice), from where both your view controllers can refer to it. That is neat practice, it not only is right from programming perspective but also extensible and helpful to anyone who deals with the code any time.
For details about how to update UI from your model, there is nothing better than starting from scratch, going through the books I mean.

I am not aware of such possibilities.
I would pass the tableview source object amongst different controllers and let the view controller handle their own table view.

I think the best approach would be to use a framework such as the freely available Sensible TableView, then use the same model for both table views. This should be really straight forward.

Related

Storyboard design pattern (to share or not to share)

This is probably largely preferential but I'd like to know if there are any reasons to decide one way or another on this.
When designing with storyboards you invariably end up with a number of view controllers. I'm looking at the overhead of a strict MVC approach where each controller is implemented in its own UIViewController subclass with corresponding UIView subclass (and even view model class for MVVM), and that seems to get out of hand quickly – it takes no time to add dozens of files to the project (many with little function). An alternative approach would be to link all the views to a common controller representative of all of the storyboard functionality.
My inclination is that if you don't have substantial controller code for any individual view controller, then the combination of all of them into one shouldn't be of harm to the readability of the code (and may enhance it over adding a large number of source files). On the other hand, if you have significant functionality to implement for any particular view controller, then it should be encapsulated within it's own controller.
In most situations I'd build all controllers to be as reusable as possible (encapsulated in their own custom UIViewController subclasses). Storyboards put this in an interesting light though since they seem to be geared towards sequences of views that typically have few entry points.
Your thinking is correct
If you don't have much functionality in each VC (ViewController) them combine all your code into one VC. The only drawback to this approach is that you won't be able to implement view specific code and every view where you will use this common VC will execute the same code whether its needed there or not. e.g. code in viewWillAppear etc.
Similarly if you have a lot of functionality for a particular view then its better to put it under its own VC
This is just a suggestion, if you need to use some common code logic between multiple VCs then instead of doing copy and paste in each VC of the same code, make it into a method of type Category and then call it where ever its needed. So change the code only at 1 place.
More VCs doesn't necessarily mean bad design. In my opinion its easier to maintain that way. My two cents. :-)
Each scene in your storyboard should have its own UIViewController subclass. Even doing it like this it's way too easy to get huge unmaintainable view controllers (MVC = Massive View Controller). Putting all the code for multiple scenes in the same view controller would create even bigger ones and also violate the Single Responsibility Principle. Each class should do only a single thing.
That also means you shouldn't duplicate the common functionality into all your UIViewController subclasses. Then they again would do multiple things - the common stuff and their actual purpose. Instead you can put your common code in other controller objects (which are not descendants of UIViewController) and use them in your view controllers.
Depending on the usecase a common base class would work as well, but it's always preferable to use composition instead of inheritance.
Another nice thing about other controller objects is that you also can add them directly in Interface Builder and connect actions and outlets to them. Your main view controller class often doesn't even have to know they exist.

iOS controllers for custom views

I'm all for trying to create lightweight view controllers (testability, separation of concern, etc. etc.), however, I've been unable to find a reasonable solution or pattern when it comes to certain cases.
A very common case (with plenty of examples out there) is separating the view controller from a tableview's delegate & datasource; I get this, it makes complete sense. But what about cases where a view controller may contain multiple custom views of varying complexity? What should be responsible for controlling each of those views? Surely not just the parent view controller.
I tend to think of a 'UIViewController' as more of a screen controller that is heavily coupled with the UI framework and its events; it does not have a single responsibility of controlling one particular view. To further illustrate my point, imagine a tableview with a couple of different prototype cells - some of which are fairly complicated and may require network access for instance - how should this be managed? Surely no single view controller, datasource or delegate should act as the "controller" for all of these cells? And a lot of that logic/responsibility does not belong in the cell views themselves, so it needs to be delegated somewhere.
One option I've thought of is to just create controller objects (subclasses of NSObject) that act as "view controllers" for the custom views I create, such as a controller object for a complex tableview cell - its single responsibility is to manage that one particular view. The tableview cell then delegates to the controller object, which then (if needed) delegates back to the parent UIViewController. Whilst this will work and helps to separate concerns, it starts to feel a bit awkward with all the layers of delegation going on.
Does anybody have any good suggestions on handling these scenarios or know of good code examples out there that demonstrates this?
Thanks!

Pattern for class to manage view controller flow

At the moment I'm using a Singleton class to do some work but I'm wondering if there is something better.
I have an app that has a completely dynamic work flow. It uses a navigation controller but the order of the view controllers depends entirely on some data that is downloaded from our server.
The entire workflow is downloaded and saved in an array.
The "main menu" screen of the app has several choices (settings, recent, etc...) these are fixed but one of them is the dynamic one. It always starts with the same type of view controller but from then on it depends on what you choose.
Description
There are 4 different types of these dynamic controllers.
Table View Controller with single selection and detail indicators.
Table View Controller with multiple selection and checkmarks.
View Controller with a text field and keyboard.
View Controller (with other related VCs) used for searching for accounts on the server.
When you press the option "New Event" on the main menu the menu then goes off to the singleton (EventManager) and tells it to start a new event.
The singleton then pushes a single selection dynamic view on the nav controller and gives it the initial options.
From here on the singleton picks up all the selections and works out what type of view is required next.
I hope this is making sense
Anyway, I don't like the singleton pattern here as I don't think it should be a singleton.
What I would like is a class that I can create from a ViewController and this class will then control the pushing and popping and flow of data between a load of different view controllers. Then when you go back to the main menu this class can go away so I create a new class each time.
Is there a pattern that I can look at that will do this? Or should I stick with a singleton like I am now?
I hope this makes sense.
EDIT
Could I use a UIPageViewController for this? Then the datasource/delegate object of the UIPageViewController will take the place of the Singleton I am currently using... or something?
ADDING PHOTO FROM TWITTER REQUEST
Each VC along the flow has no idea what cam before it or what comes next. All they do is call back to the singleton to say "This value was selected" or "This text was entered" etc...
The singleton then stores that info and works out what comes next and pushes the next VC onto the stack.
It needs to be able to move back along the stack so the user can go back to change something etc...
It's all working as it is I just don't like the use of the singleton.
Lots of comments here in order of importance.
Everything you've described here sounds really good, even down to the naming. "EventManager" sort of sounds like it manages all "events" in the system (so I'd expect there to be a class called Event, but that's a tiny quibble and the name is likely still very good). There are other good designs, but I wouldn't have any problem with yours.
I agree that this does look like a good fit for UIPageViewController. You should certainly investigate that to see if it's the right fit. It's always nice to use a built-in controller if you can.
There's no reason to strongly avoid singletons. They are a natural part of iOS development and fairly common in good Cocoa design. They should be "shared" singletons generally (never create "strict" singletons that override +allocWithZone:). This just creates an easy-to-access instance rather than a true "singleton." This is the way things like NSNotificationCenter work and is often a very good pattern.
Singletons are best when many random pieces of the system need to access them directly and passing them around to everyone would be a lot of overhead (especially if many of the pieces you'd have to pass the object to don't need it themselves). Again, think NSNotificationCenter. If the users of it are mostly contiguous (i.e. most objects you would pass it to actually need it themselves), then just create one at the start of the program and pass it around. That sounds like your situation, so your intuition about it seems good. Just de-singleton it and pass it. Easy change.
But I'd definitely dig into UIPageViewController. It could match your problem very well.

What is the best practice to control multiple views?

I have this view in the storyboard:
as you can see there are some fixed controls, and others that change according to the type of screen.
What do you think is better?
1- Same view controller for multiple screens. (more code to control views)
2- Add all controls in the same screen, then hiding and showing them by code? (messy code)
3- View controller for each screen. (replicated code)
Don't use the word "window", which can lead to different interpretations of what you are trying to say. Use the word "screen", or "section of the screen". In this case, I would use a container of UIViewControllers. To communicate between then, use KVO or NSNotificationCenter (most probably the second one). Also make sure to not have the data source directly on the UIViewController (like an array or a dictionary). Keep the Data Source somewhere else, where all the UIViewControllers (or any class) can easily access. You could go with a Singleton.
Putting the Data Source away, and not directly on the UIViewController, gives you more flexibility over your code. If you ever need to use a new UIViewController, nothing is changed, he can still request resources from the same point. So keep that in mind.
Edit 1
The data source also is inside the view controller, there is no
interaction between screens, it's the same screen but some controls
changes according to the type of it, what do you think I have to do
now?
The problem with this kind of approach is that if you need, for some reason to add a new UIViewController, that also use the same data source, what do you do now? I always try to decouple as much as possible the UIViewController from the Data Source. Otherwise you might have problems in the future, if the application changes (client's needs change). Again, moving the Data Source to a proper class, and use a Singleton to access it.
UIViewController <=> Singleton <=> Data Source
So now you suggest to make multiple view controllers with multiple screens?
I suggest a UIViewController to act as a container for the others UIViewControllers. For me it makes more sense to compose the Screen as I go, than doing everything in one place.
I'd definitly go with no 3. This approach is most flexible! And it is clean => good to maintain

What is the appropriate design pattern for the following situation?

As an exercise I am working on a simple drawing app for the iPad.
I am using UISplitView, with the drawing view as the detail view. In the master view controller I present (in a table view) a list of the shapes drawn so far.
The user can edit or delete any shape from the master view controller, and also select and edit a shape by touching it in the detail view controller.
To notify each of the view controllers of the changes made by the other, I thought of using delegates, but I am not sure if this is the right pattern to use.
First, as I understand it, delegates are supposed to be used when a certain object encounters an event which they don't know how to handle. in that case they pass all the information to the delegate and let it handle the event. This is not the case here since both view controllers need to do something with the information. Using delegates here can cause code repetition.
Another reason I am thinking not to use delegates is that in the future I might want other view controllers to get the information of changes in the drawing. I can use multiple delegates (is it good practice in general?) but I'm not sure this is a good solution either.
Are there other solutions I should consider?
On the contrary, I think delegates might be the right pattern to use here - you don't necessarily delegate only when you can't handle an event (though that might be one situation where you would delegate).
Instead, consider delegates a way of getting information to or from another object, when you simply don't know what that object might be. For example, Apple uses the delegate pattern when working with UITableViews; in that delegate protocol, the table view knows perfectly well what to do in each situation, but still notifies your code when certain actions are about to happen. I think that's an excellent parallel for your situation. (Note that a parallel to your question's assumptions also exists, in the UITableView "data source," where the table view does require some bits of information.)
Another technology you could consider using, if you're really dead-set against delegates, would be to use notifications. You can have each controller subscribe to particular notifications, then have your shape (or detail view controller) post instances of NSNotification when observable changes happen. That way, you still get to handle events happening in a different controller, but without needing to maintain a delegate list.
As for code duplication, just consider refactoring as you start encountering situations where you would duplicate; maybe you should design a single delegate or notification subscriber object for the common code, then only do class-specific things in each of the other controllers?

Resources