Is using protocol and delegate to create a Control like UITableView the optimized one? - objective-c

The UITableView can be used to create a list view if the at least the UITableViewDataSource is adopted by the relevant class. I have the below questions:
Why is it designed in such a way that based on the section and row , the controls are created through data source methods and given back to the UITableView instance. Why not provide all these information in UITableView instance with out using the UITableViewDataSource. What difference is it going to make?
EDIT1:
#hermann and #JOhn: You have mentioned that it breaks the MVC pattern. Let us assume I am creating a custom UITableView like control myself. I design it in such a way that I do not pass the data directly to the UITableView but instead I pass the relevant subviews that needs to be added in the rows and section and their relavant headers alone. I think this will not break the MVC..Am I correct? But still it has the problem that the current UITableView implementation style solves..the ability to reuse controls and images instead of bloating the memory usage.

First, doing so allows to stick on the MVC pattern. A UI object, meaning a view, should never directly communitcate with the model, wich is the business data. Plus it should not perform any business logic, which belongs to the controller.
Second, it is more flexible without the need of subclassing the UITableView object.
Third, the full concept is quite efficient from a performance and memory management point of view. Instead of loading all data upfront, that may be displied within a table, it can be fetched or calculated or whatever on a just in time "need to know now" basis.
Plus data containers, especially memory consuming once like images, can be released as soon as the data has been provided using the delegate/data source methods.
Of course, a subclass of UITableView could do the same in principle. I just doubt this would result in more maintainable code or even save any time or work resprectively.
If you don't want to stick with MVC, then feel free to subclassing the table view and hand all its data over in its init method or enable the table view subclass to load all that data from webservices or data bases or wherever it comes from.
And when you run into problems and get back to us searching for guidance, then be prepared for some nasty replies like "Why don't you stick to the established best practices or the MVC pattern?" ect.
In the event that your very table just displays some rather static values, such as if it just acts as menu for further navigation drill down etc. then this concept may look a bit rediculous. But it does not hurt either. And when it comes to more complex tasks of data providing then it certainly has its advantages.
Give it a chance. Give it a try!

For MVC you want to try to clearly separate what the model, controller, and views are responsible for doing. By allowing the view (tableview) to ask for the data from a delegate, the view can be create extremely generalized.
Using the delegate pattern, the controller can "stage" the data in anyway that is wants and then give it to tableView as the tableView needs it. The tableView doesn't care where the data comes, how it was transformed, what ADT is used, nothing. It is complete ignorant to where or what the data is. All it knows it should show this string at this location for this section and row.

Related

Inserting controller logic between model and view when using Interface Builder, NSObjectController sub-classes, and bindings

I've been struggling to understand the best way to insert controller logic when using IB, NSObjectController sub-classes and bindings.
I need to insert controller logic between the model and the view, and I'm struggling to find an elegant way to do so. Yes, you can send actions to the file owner and handle controller logic in there, but when some core data models can extend across fifty entities or more with deep relationship structures, this starts to mount up to an incredible amount of boiler-plate code.
A very simplified example would be this; imagine you have an entity with four string attributes myTextWinter, myTextSpring, myTextSummer, myTextAutumn. You have a view which connects to this in IB via an NSObjectController. Now, say the user can select which 'Season' they wish to view by choosing Spring, Summer, Autumn, Winter from a Menu somewhere - when that season is selected, I would like to display the appropriate season's text.
In this simplified example I could probably fetch the object in the NSDocument sub-class, create a property called mySeasonText which I bind to in my view, and then check my NSUserDefaults for the appropriate season and route the requests to the appropriate attribute in the model.
The problem comes when I have fifty entities, some with relationships some two, three or more deep, each with their own set of season specific text attributes that I wish to switch between when selecting from the Season menu. Or if I have a bunch of nsarraycontrollers chained together to access objects at a deeper, and deeper level.
To date, I've been doing the following; adding a property in each of my model objects called 'mySeasonText', then grabbing the setting from my controller setting, and routing to the appropriate season. I refresh these objects whenever a new item in the menu is selected.
Whilst this works and eliminates an absolute ton of boiler-plate code, my controller logic is now in my model.
There must be a better way! Could someone please point me in the correct direction?
This is a tricky topic. Apple even mentions these challenges in its own documentation:
By using the bindings technology, you can easily create a Cocoa MVC application whose views directly observe model objects to receive notifications of state changes. However, there is a theoretical problem with this design. View objects and model objects should be the most reusable objects in an application. […] Design-wise, it's best to keep model and view objects separate from each other, because that enhances their reusability.
The design pattern you are looking for is a Mediating Controller - a way to use the cocoa-bindings classes to insert controller logic:
Mediating controllers are typically ready-made objects that you drag from the Interface Builder library. You can configure [Mediating controllers] to establish the bindings between properties of view objects and properties of the controller object, and then between those controller properties and specific properties of a model object. As a result, when users change a value displayed in a view object, the new value is automatically communicated to a model object for storage—via the mediating controller; and when a property of a model changes its value, that change is communicated to a view for display.
Here is how I like to think of them: Have you ever seen a movie or TV show where two characters need to talk, but they don't speak any of the same languages? They find someone else (or in a comedy 5 other people) who each have one language in common, and they communicate by playing a giant game of translation telephone.
Mediating controllers are kind of like that.
As your application grows they learn all the super specific rules about where to look for this one thing on this one view. This is the kind of code that an app needs to run, but you rightly feel that it is nasty when put in your model.
For several specific and detailed examples, Apple provides this amazingly detailed document: Bindings Message Flow.
For some really good discussions about this and related MVC + Bindings please see:
MVC and cocoa bindings best practices question
Why use NSObjectController?
Replacing model objects using an NSArrayController

iOS architecture and components

For quite a while I've been looking at objective c examples, watching the Stanford lectures, and playing around with some code to get a hang of creating an iOS app.
However there are a few things that I can't find a good answer on:
How do I properly separate my layers? I understand the MVC structure, and I saw some examples of creating Categories for models to implement business logic. Is that the proper way, by enriching models or should I create dedicated classes (e.g. to authenticate users, extract models from json, group orders)?
How smart should views be? Can I make a view that displays a Contact (by assigning the contact property) or should I create separate properties for all of the Contact fields or should the view request it's information via a delegate call?
I'm using a Storyboard in my application. On my screen I want to
have a navigation bar, and let's say a view that displays orders. On
other screens I want to reuse the order-view.
How can I re-use the order-view's ViewController and View in other ViewControllers?
If I have 4 screens with the same look-and-feel, do I have to simply copy them in the Storyboard? This seems like a pain to main, what if I want to change my background? Or add a button to all of the views? When I create a setup-wizard I don't want to define the look-and-feel for every screen separately.
Coming from a C# background I probably have to get into the objective-c mindset :)
Any help on this would be great.
1) ObjC-Categories will easily distort your understanding of the main problem you're facing. ObjC-Categories are completely unnecessary. You could always approach these extensions by subclassing, object composition, additional methods in the actual model, or some customization in the controller or view. So if you need to format data (e.g. which is present in the model) for display in a view -- that task would often land in the controller. As far as the examples you provide: You may opt for models in simple cases -- as well, any of the examples could merit dedicated class, if complex enough or if it would keep you from redundant implementation. Note that these may be accessory classes, which simply produce a model, or they may be composites of multiple concrete of abstract classes. Not everything needs to land squarely in the definition of M-or-V-or-C. You're free to use many design patterns with ObjC. Think of MVC as the patterns Cocoa typically uses -- you will need to know them, and you will need to know how to subclass and extend these types, but these patterns lose dominance as implementations move away from Cocoa's libraries (e.g. as complexity increases).
2) They can be smart. However, under MVC, you want to focus its implementation on the view/presentation aspect. A view which represents a collection of information could in fact perform some tasks which are typically reserved for the controller -- however, you would generally cede that the implementation were a dedicated MONContactView in doing so. If you go that route, you would generally do so for easy reusability or to achieve a simple interface. Displaying information about a Contact could be very complex - In simple scenarios, these tasks are often handled by the controller. Specifically, a MONAwesomeContactView is likely less complex (e.g. in SLOC) than MONAwesomeContactViewController (unless you have some very special drawing or layout to perform). It would be more common to set the controller's contact, and let the controller push the contact data to the views' fields. Again, in the case of a very specialized subclass -- a view could very well hold its own controllers in some cases.
3a) There's nothing wrong with creating multiple instances of a class.
3b) No need to copy. When duplication is smelled, I push the implementation to actual code -- the programs can apply the look and feel you desire, or add or manipulate the subviews as you desire. Of course, they will not be present in Xcode's NIB editor. There are of course alternate approaches, but this replication often makes me move the implementation to compiled code. Achieving a good balance of both is not so difficult (personally, I do most of my views programmatically, rather than using NIBs).
This is a pretty abstract question and it's not clear what oh mean by 'layers'. Yes, you should create your own classes where appropriate, but categories also give you the option of adding functionality to existing classes. If you can be more specific with the question it'll be easier to provide a better answer.
It's a judgement call. If you want to create a view class that knows how to display an instance of your Contact type, that's fine in my book. If that view knows where Contacts are stored in the app, though, that's not so good.
Remember that the things in a storyboard are objects, not classes. You don't want to try to re-use a view from one scene in another scene -- that'd mean sharing a view between scenes, which really won't work. If you want to use the same order-view in several places, that'd be a good candidate for creating a class. On the other hand, you can set up your storyboard so that several different scenes all transition to the same scene. If you want different parts of your app to modally display a scene that displays an order, for example, you can do that.

Objective-c class design/organization

I've created my first iPhone app that presents audio tracks of a similar genre in a tableview. The user can play audio tracks using ipod-like controls which streams mp3.
All of my code is in two main classes: RootViewController and CustomCell.
My RootViewControllerClass is massive. I'm assuming it is poor design to stuff almost all of my code in one class?
Initially, I thought it made sense because I only have one View Controller. To practice better coding conventions, I'd like to split up my RootViewController class into smaller, specific classes (assuming this is the correct practice?).
Here are the components of RootViewController that I plan to separate out into individual classes:
DataSource - pulls data from server; modifies and organizes the data for the tableView
TopChartsView - includes buttons in a view to modify the audio tracks(dataSource) by top rated weekly/monthly/all-time
GenreChange - includes buttons in a view to filter the dataSource by genre
AudioPlayerControls - includes buttons in a view that are similar to iPod controls
Am I organizing my classes correctly? It seems to make sense that I organize my classes by function. However, I'm having difficulty grasping how classes should interact with each other in an ideal design.
Do I use protocols and delegation to link my classes together?
Designing iOS apps is mostly about the MVC design pattern, which means that you seperate your model, view and controller. In your case I would put the DataSource logic in a seperate file or files (it's your model). This also makes it easier to reuse the same logic in another view controller in a later point. Maybe you can also subclass your UITableView if lots of code resides there.
Protocols and delegates are a great way to connect your classes and they are very frequently used in a good design. Since you don't have many viewcontrollers in your application (as far as I see), there are not very much opportunities to use them, please correct me if I'm wrong ;)
It's more about object-oriented-programming than especially about iOS and I think, you should get familiar with some concepts of OO-Design (if you really interested), but from my point of view you don't have to. To answer your questions first:
I'm assuming it is poor design to stuff almost all of my code in one class?
Some say so...
Am I organizing my classes correctly?
Hard to tell, by the information you gave.
Do I use protocols and delegation to link my classes together?
Not necessarily.
But: If your code works fine, you are the only one, who works on it, you don't plan to re-use your code as a library or by taking full classes from it (i.e. if you only plan to copy & paste), there is no need to refactoring everything just for the sake of doing it.
Even though: If you want to move forward or if you're planning to write libraries or something, it would be a good idea to learn about OO (sometimes it's even entertaining). Since you're working with objective-c this one from apple's docs could be a good start to learn.
And: If you read a bit about OO-programming and (more important) take the time and to read code of others, you'll know how and when it is useful to organize your own code.

Is it good practice to use one UIViewController for both adding and updating records?

I'm developing an app for iPad. I have a form (UIViewController) for adding new records (of type Person) to my sqlite3 database.
For updating (i.e. modifying) records, I was considering using the same UIViewController, but I want to know what's better: one UIViewController for adding and another for updating, or one UIViewController for both adding and updating?
It depends on the amount of overlap.
If updating a record presents all the same information as creating a record, then it will be less lines of code, and less duplication, thus easier to maintain if there is one view controller.
You could even have two different storyboard views using the same view controller. This will let you give a different look when creating or updating records. I think it's good to have a noticeable visual differences for different operations. It gives a visual clue to the user as to what operation they are currently performing.
On the other hand, if there are different business rules when updating records, or if there is a different workflow when creating a new record, then two view controllers may prevent lots of branching code reducing the cognitive complexity.
In this case, you may want to consider subclassing one view controller from the other.
The question is a little vague. Let me check my understanding:
You're writing code in Obj-C that involves a type called Person that has some information
You have a form by which a human fills out the information in type Person.
You then helpfully give that human an "updating" notice of some sort, so they know you're working hard, not hardly working.
Your question is whether you should use one UIViewController for the form and one for the updating notice, or use one that covers both cases, correct?
If that's your question, I'd answer that it's largely a matter of taste, but you probably don't need a whole new UIViewController for the update notice. I'm not even convinced you need a different view, never mind its controller. You can do it either way as you prefer, but I'd recommend the simplest option that does what you need.

Implementing Model-View-Controller the right way

Working on a game in Objective-C/Cocoa for OS X, and I finished the prototype as much as it's worth being finished. It's a mess of code, being my first game, but everything works. I've been reading up on the best way to put things together, and MVC seems to make the most sense, but I'm a bit confused.
Where does it start? With the controller? That seems to make the most sense to me, but how is it started? In my mess of a prototype, I have everything starting from the init of the view and going from there. Would I just do the same for the controller, and put what's needed in the init? Or is there something else I can use to do this? If it's started from the init, how do I init the controller?
How would I set up the game world? I currently use two arrays, one for the world (Walls, Floors, Doors, Water, Lava, etc.), and one for the items (I'll be adding a third for characters). The map (a .plist) is loaded, and then the objects are created and added to the array it belongs to. Where do the arrays go? In the prototype, they're also part of the view, so I guess you could say I combined the two (View and Controller) together. Would there be a Map object created for each map? Would there be a Maps object that contains all of the maps?
How does it all work together? The player presses a key, which moves the character in the game. The view would be handling the input, right? Would you send that to the controller, which would check for everything (walls, monsters, etc) in the map/other arrays, and then return the result? Or would you send it to the player, which would go to the controller, which would do all of the the checks, and then return the result?
I thought I had it pretty nicely laid out in my head, but the more I think about it, the less solid my ideas become and the more confused I get. By all means do not hesitate to draw something up if you think it will get the point across more efficiently.
If you've taken the time to read all of this, thank you for your patience. From what I've gathered, most people that write code don't use any sort of design. After reading up on this, I can see why some people would avoid it, it's confusing and people seem to think it isn't worth the time. I personally think that the advantages totally outnumber the disadvantages (are there any?) and it only makes sense to keep things organized in a way that you won't have to do a total rewrite every time you want to implement a new feature. You wouldn't build a house, car, or an appliance without a design, why would you write a complex program without one?
I asked this question because I want to do it the right way, instead of hacking and half-assing my way to "victory".
You may be interested in a presentation I gave to ACCU '09 - "Adopting Model-View-Controller in Cocoa and Objective-C".
Where does it start? With the
controller? That seems to make the
most sense to me, but how is it
started?
Create a new Cocoa app project and you'll see that there's already a controller class provided by the template - it's the app delegate class. Now look in MainMenu.xib. There's an instance of the app delegate, and it's connected to the "File's Owner" object's delegate outlet. In this case the NSApplication is the File's Owner; it's the thing that wanted MainMenu to be unpacked. So this really is the delegate of the application.
That means we've got something which is a controller object, can talk to the NSApplication instance, and can have outlets to all the other objects in the XIB. That makes it a great place to set up the initial state of the application - i.e. to be the "entry point" for your app. In fact the entry point should be the -applicationDidFinishLaunching: method. That's called once the application has finished all of the stuff needed to get your app into a stable, running state - in other words Cocoa is happy that it's done what it needs to and everything else is up to you.
-applicationDidFinishLaunching: is the place where you want to create or restore the initial Model, which is the representation of the application's state (you could also think of it as representing the user's document, if that analogy is suitable for your app - document-based apps are only a little more complex than the default) and tell the View how to represent things to the user. In many apps you don't need to load the whole Model when the app has launched; for a start it can be slow and use more memory than you need, and secondly the first View probably doesn't display every single bit about the Model. So you just load the bits you need in order to show the user what's up; you're Controlling the interaction between the View and the Model.
If you need to display other information in a different View - for example if your main View is a master view and you need to show a detail editor - then when the user tells you what they want to do you need to set that up. They tell you by performing some action, which you could handle in the app delegate. You then create a new Controller to back the new View, and tell it where to get the Model information it needs. You could hold the other View objects in a separate XIB, so they're only loaded when they're needed.
How would I set up the game world? I
currently use two arrays, one for the
world (Walls, Floors, Doors, Water,
Lava, etc.), and one for the items
(I'll be adding a third for
characters). The map (a .plist) is
loaded, and then the objects are
created and added to the array it
belongs to. Where do the arrays go? In
the prototype, they're also part of
the view, so I guess you could say I
combined the two (View and Controller)
together. Would there be a Map object
created for each map? Would there be a
Maps object that contains all of the
maps?
We can work out what objects we're modeling by analysing your statement above - you may not realise it, but you've sketched out a specification :-). There's a world which contains walls, doors etc., so we know we need objects for those, and that they should belong to a World object. But we also have items and characters - how do they interact with a world? Can a place contain water and a character? If so, perhaps the world is made up of Locations, and each Location can have a wall or a door or whatever, and it can also have items and characters. Note that if I write it like this, it seems that the item belongs to the location, not the location to the item. I would say "the mat has a cat on it" rather than "the cat has a mat underneath it".
So simply think about what you want your game world to represent, and the relationships between the things in the game. This is called domain modeling, because you're describing the things in the game world rather than trying to describe things in the software world. If it helps, write down a few sentences describing the game world, and look for the verbs and nouns like I did in the last paragraph.
Now some of your nouns will become objects in the software, some will become attributes of other objects. The verbs will be actions (i.e. methods). But either way, it will be easier to think about if you consider what you're trying to model first, instead of jumping straight down to the software.
How does it all work together? The
player presses a key, which moves the
character in the game. The view would
be handling the input, right? Would
you send that to the controller, which
would check for everything (walls,
monsters, etc) in the map/other
arrays, and then return the result? Or
would you send it to the player, which
would go to the controller, which
would do all of the the checks, and
then return the result?
I like to follow the "tell, don't ask" policy, which says that you command an object to do something rather than asking it to give you the information to make the decision. That way, if the behaviour changes, you only need to modify the object being told. What this means for your example is that the View handles a keypress event (it does because they're handled by NSControl), and it tells the Controller that this event occurred. Let's say the View receives a "left arrow" keypress, and the Controller decides this means the player should move left. I would just tell the player "move left", and let the player sort out what happens when moving left means bumping into the wall or a monster.
To explain why I want to do it that way around, imagine that you add in game 1.1 the ability for the player to swim. Now the player has some ableToSwim property, so you need to change the player. If you're telling the player to move left, then you update the player to know what moving left over water means depending on whether they can swim. If instead the Controller asks the player about moving left and makes the decision, then the Controller needs to know to ask about being able to swim, and needs to know what it means near water. As does any other controller object in the game that might interact with a player, as does the controller in game for iPhone ;-).
It seems like your main confusion is how things are constructed during app start up. A lot of people get stuck on this, because it feels like something magic is going on, but let me see if I can break it down.
App is launched by user
C main() function is called
main() calls NSApplicationMain()
NSApplicationMain() load the MainMenu.nib (or another nib specified in the info.plist)
Nib loading initializes all of the objects defined in the nib (including the application delegate)
Nib loading makes all the connections defined in the nib
Nib loading calls awakeFromNib on all the objects it just created
-applicationWillFinishLaunching: is called in the application delegate.
NSApplication (or a subclass specified in the Info.plist) is initialized
-applicationDidFinishLaunching: is called in the application delegate.
Note that the application delegate is initialized BEFORE the NSApplication (sub)class. That is why application(Will|Did)FinishLaunching: takes a notification as opposed to the NSApplication it is a delegate of.
The general consequence of this is that your views are created for you via nibs, and you controllers are created as a side effect of nib launching since they tend to either be root level objects in the nibs, or the nib's File's Owners. Your model is usually created either in the application delegate or as a singleton that is lazily initialized when something first access it.
You should create a model for the the whole game. It should contain everything about the game except the GUI interaction. The views, on the other side, contain all GUI stuff without knowing anything about the game flow.
The whole point is that models and views are expected to be reusable. The model classes should play with any GUI (and maybe even the console or command line). The view classes should be able to be used with other similar-looking games. Models and views should be completely decoupled.
Then, the controller fills the gap. It reacts on user input, asks the model classes to perform a specific game move, and asks the views to show the new situation. The controller is not expected to be reusable. It's the glue which holds the game together. The controller ensures that model classes and view classes remain indenpendent and reusable.
In addition, don't try to make the design perfect from the start. Don't hesitate to refactor at any time. The faster a bad design decision gets corrected, the less evil it does. Designing everything upfront means that a bad design decisions won't be corrected at all, unless you make a perfect design upfront, which is simply improssible even with decades of experience.
Always remember the third design rule of the X Window System: "The only thing worse than generalizing from one example is generalizing from no examples at all."
For your game the model would include things like the current position of the character, the number of health points, and other values that involve the "state" of the game. It would notify the view whenever something changed so that the view could update itself. The view would simply be the code required to show everything to the user. The controller is responsible for responding to user input, and updating the model when necessary.
The controller is the central component in this, and it is what should instantiate the model and view.
When the player presses a key, the view should simply pass that command onto the controller, which decides what to do.
You are wrong that most people don't design. Perhaps most amateurs, or perhaps the people who ask the most questions online, but not anyone working on a project that is even somewhat sophisticated. Professional programmers are all experienced in software design; without it they literally would not be able to do their job (write software to do X).
Your game sounds like it is complicated enough to warrant an architecture pattern like MVC. There are some instances where a piece of software is simple enough that MVC is overkill and needlessly complicates things, but the threshold for using MVC is pretty low.
You might find this article Introduction to MVC design using C# useful. Although the example is in C#, the principle should apply.