I'm making an application that does calculations.
i have a bunch of views and view controllers.
the user clicks buttons to open up and close areas of the screen triggering animations. certain text fields are disabled when others are edited. when you click calculate a bunch of math is done, and results are animated to the screen.
the views.. are all that stuff we do with the xib file or storyboard
the controller is.. the view controller that we start with when we make an ios app.. we reference outlets and actions
3.. the model is ??? im assuming the math i perform should go in the model.. any computational stuff that isnt directly affecting the view. but where the hell is the model?! do i just create a general object and instantiate it inside the controller? In all the tutorials ive seen .. i just see people use view controllers and associated views.
The model is not something that comes standard like the rest of the things you mentioned. When building a single view application in Xcode it comes with a viewController and an appDelegate. As you noticed, the model is missing.
That is because you build your own model. A model is typically an object you instantiate in your view controller and then manipulate your data through its methods. The model will be a .h and .m file that you make to create an object that, through its methods, manipulates the data from the user input.
Because it is not good practice to have your view directly talking to your model, and vice versa, your viewController acts as a liaison. The view (buttons, labels) contains on screen data that the viewController can access. Once the viewController has access to this data, it sends that data to the model. As stated earlier, the model can be an object that you instantiate in your viewController. It does the thinking of your app and manipulates the data that your viewController sends it.
A good place to instantiate your model is in the viewDidLoad method. This ensures that when your app is ready, your model will be too.
- (void)viewDidLoad
{
[super viewDidLoad];
self.myModel = [[Model alloc] init];
}
And the reference to your model as an instance variable should be put in your private class extension at the top of your viewController's .m file.
#interface ViewController ()
#property (nonatomic) Model *myModel;
#end
As always the design is upto you. I would suggest creating a core data model with what ever model objects you require (This will generate the class files for you). Becoming familiar with core data early in your iOS learning is a great way to pick up best practices.
This should get you started. Doing it this way will also allow you to easily persist the programs state, is easy to maintain and extend.
Good luck with your iOS development.
Yes, you should create an NSObject subclass and put your calculations inside it.
Yes, your Controller should then create the Model object, and use it to coordinate the View.
The term "Model" just refers to the collection of classes that you use independently of the UI. A poorly designed app may not have a Model at all. A well designed app will keep its Controllers free from being cluttered with business logic by providing a suitable Model.
A rough guideline to keep your Model delineated from everything else is that your Model should never #import <UIKit/UIKit.h>.
Your math actually goes in your view controller. Unless you want to reuse the same functions for various other methods.
Your model would be anything you want to store to Core Data or some other persistent storage.
Basically Views talk to the UI, Models to the Database, and everything else to the controllers
Related
In my application there are two view controllers that navigate to a DetailsViewController.
Right now, when the DetailsViewController appears, I fetch data from the server and display it on the UI. I dislike this because the UI is blank while the network request is going on. What I want is that the data be loaded in the previous view controllers and then passed to DetailsViewController.
Now the problem is that I have the exact same "load-data-and-then-push" code in two view controllers and I'm not sure what the most sensible way is to remove the repetition.
One idea is to have the two view controllers inherit from a common superclass which contains the loading/pushing method. I don't like this strategy because, supposing I have more ViewControllers like DetailsViewController down the line, I wouldn't like to write a loading superclass for each one.
Another idea would be to define a static method in the DetailsViewController which the two view controllers can invoke but this method contains UI related code (specifically, code to show an HUD Progressbar and a UIAlertView in case network fetch fails) which makes me uncomfortable.
I am very new to iOS and Objective-C so I might be missing something simple and obvious.
My favorite would be in this case to create a new class which handles the loading of the data (like http-request, etc.) and to create a delegate protocol for this class. This delegate callback might then be implemented in your two viewControllers which would then perform the push segue to your DetailsViewController when called. Delegation is a very nice and powerful feature, check out the documentation here: Delegation
Well, I'd better write it in the comments, but I have no reputation for that.
Imagine you are reading a json with several students information (name, year, etc.)
you can create a student object with the property that will be read and an object that will have a method that will run in the background that will be responsible for accessing your WS (JSON or whatever it is) and record this information to the student object. So if you have 10 students you will have an NSArray containing 10 students. This array is what you will for your next viewcontroller.
It is a lot of code, but you think examples easily.
If you use Storyboards you can use prepareForSegue: sender: to pass your data/model class to your DetailsViewController. If you use xib's you can do the same after instantiating the DetailsViewController and before pushing it.
If you need to load subsequent data from your server you should write a class that does this network stuff for you.
If DetailsViewController needs to load some additional data, you can use something like a loading view like Andy suggested. This is a widely used method.
If I want to build a generic UI Component (one that will handle its own view and logic, data source,
etc), is it a good practice to subclass UIViewController?
I would say no. But it depends. If your component manages other view controllers or has/will have any kind of logic that's not specific to a view (e.g. navigation logic, business logic etc) , then you should subclass a view controller. Then again that makes it more than an UI component.
Otherwise, you should subclass an UIView, like Apple does with many components, including UITableView (speaking of datasource), GLKView, UICollectionView.
My overly simplistic answer is "no, when building a generic component do not automatically start with a UIViewController subclass". However that alone is not a useful answer and in some cases a UIViewController subclass is exactly the right solution.
Instead let's consider how to decide what your component should be. I think the best way to figure that out is to answer three questions:
What is this component responsible for?
How do you want to interact with it?
What are its dependencies?
In all cases we can try to start as simple as possible and add complexity only when the answers to those questions require it.
Could this component just be a function? No objects, no classes, if all you want to add is some behavior then maybe all we need is a function. If this behavior only applies to specific existing types then maybe we need a category on an existing class.
Not enough to cover what we want to do? Ok, I guess we might be talking about a new type so let's create a class. Can it just be a subclass of NSObject?
Want to display something in a view? Ok, then we at least have a UIView subclass, maybe a UIControl subclass if it is more interactive.
The view needs some data to back it? No problem sounds like we now need two pieces; a view to display data and a data source to provide it. Here the view shouldn't need to know who creates and owns this data source. As long as one was provided to the view we can use it, anything else is outside of the view's area of responsibility. Similarly we might add a delegate to notify some other object of interactions with the view.
If we still haven't covered all of this component's responsibilities then maybe we need yet another piece, something in the controller layer to manage our view. We're still not (yet) talking about a UIViewController though! It's fine to have a "controller" or "service" that is a NSObject subclass. If all this piece needs to do is manage network connections, or map NSFetchedResultController results to our view's data source protocol and update the view, or just provide a convenient implementation of the most common mapping of model objects to the view's data source then a simple "controller" object is still all we need.
Still not enough? Finally we get to the point where we consider providing a UIViewController subclass. Maybe we want to allow users of the component to just present a modal view controller to hand off responsibility for an interaction (send an email, compose a tweet). Maybe there's a common set of default behaviors we want to provide that are tied to view controller life cycle events (UITableViewController flashing scroll bars in -viewDidAppear:).
Build your component from the pieces you need to support the behaviors you want to provide but keep it as small and simple as possible.
Yes, it's good practice in many cases. The iOS SDK contain many examples of UIViewController subclasses. A few of them contain only a small amount of generic behavior and are essentially useless without customization:
GLKViewController
UICollectionViewController
UITableViewController
And some of them provide significant generic behavior but are still mainly containers for your own view controllers:
UINavigationController
UIPageViewController
UISplitViewController
UITabBarController
But most of them are essentially complete packages with little or no need (or ability) to customize their behavior:
ABNewPersonViewController
ABPersonViewController
ABUnknownPersonViewController
EKCalendarChooser
EKEventEditViewController
EKEventViewController
GKAchievementViewController
GKFriendRequestComposeViewController
GKGameCenterViewController
GKLeaderboardViewController
GKMatchmakerViewController
GKTurnBasedMatchmakerViewController
MFMailComposeViewController
MFMessageComposeViewController
MPMediaPickerController
MPMoviePlayerViewController
PKAddPassesViewController
QLPreviewController
SKStoreProductViewController
SLComposeViewController
TWTweetComposeViewController
UIActivityViewController
UIImagePickerController
UIReferenceLibraryViewController
UIVideoEditorController
If you think about what all of these have in common, you may conclude that they all have two things in common:
Each has a specific model (in the MVC sense) that it interacts with, and that model is not specific to your app. The models vary widely (UIVideoEditorController's model is a single video; UIImagePickerController's model is the entire photo library; GKAchievementViewController's model is a database possibly on an Apple server in “the cloud”), in some cases you provide the model (or some properties of the model) up front, and in some cases you receive the model (or a fragment of it) at the end. But in every case, the view controller handles all the interaction between the user and the model with little or no ongoing help from your app.
Each provides its own view hierarchy, with little or no customization required (or even permitted).
In other words, each of these view controllers isn't just the “C” of an MVC pattern. It's the tip of an entire MVC iceberg.
If your component is also an MVC iceberg, then exposing the tip of your iceberg as a UIViewController subclass is quite appropriate.
It depends on the iOS version you used.
A. prior to iOS 5.0, It's not a good practice, and not recommend.
B. start with iOS 5.0, It's just ok.
subclass a view controller for a UI component (UIView), , that means you wanna use the view controller life cycle method, to manage the user interaction and view display procedure, data model etc. So, if the life cycle method can not easily automatic called, the view controller is not that meaningful.
start with iOS 5.0, it's possible to create custom view controller container, so, it's ok to build custom generic ui component with view controller to add as a child view controller.
prior to iOS 5.0. Subclass a UIView with custom delegate protocol is the right way. one other thing is about the code organize. put the all custom delegate method to another custom class, not in the view controller, in the view controller just init a delegate class instance, and set this to the view delegate property.
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.
Explanation
My app basically uses a mapview with an overlay of polygons that represent buildings, coupled with an annotation. So for this it imports a custom class called Annotation that handles the popup details when the annotation is tapped, meaning it store the building's name and address. At this time the callout (the blue disclosure button) loads an empty DetailViewController object (as there's not really any data to pass through).
I soon added a new feature in the form of a searchable table that loads custom objects of the Building class (with similar properties to Annotation, plus images and more details) that then loads in the aforementioned DetailViewController class with the building's details.
So to summarise, the MapVC contains multiple annotations, which when the relevant disclosure button is tapped open the DetailVC. SearchVC is accessed by a button on the MapVC and has a table of Building objects, which loads a DetailVC with the relevant data, like so:
Next Step
So now I want to implement functionality into the blue disclosure button on the callout, so when the user taps it it'll load the building details. At the moment all it has is the annotation's details. I could add the extra properties to the annotation to make it complete but I think it's much better to just work with one custom class called Building, which has a MKAnnotation nature. Then this Building class is loaded for the annotations and searchVC's table.
Question
So finally, what's the best way to go around this? I want all the data to be stored independently of any of the VCs in the diagram. I followed a tutorial from Apple (the BirdSighting one) which uses a separate Datacontroller class, which I'd then load into other classes. Is this the best approach?
You're talking about MVC, model-view-controller. This is a very smart way to handle things, and is a good practice to get into. The model stores the data, in this case, building names, etc. The view displays data. The controller is what connects the view to the model, updates the view, gets notifications from users and in turn updates the model.
I use a singleton pattern for model data. Only one instance of a singleton is ever present in an application. That way, the data is not bound to any one particular view controller. Data only gets updated in once place, the model. It's a lot easier to trouble shoot issues with a singular point of convergence for application data objects.
I have a macro that I define in my PCH file.
#import "DataController.h"
#define DATA() [DataController sharedInstance]
In my code I can easily get to my model class by calling
DataController *data = DATA();
All of my views and viewcontrollers access objects stored in DataController, so there are never two view controllers handling separate pieces of information independently. All references point to the same place.
Some people use the AppDelegate object to store data, but it can quickly turn into a 1000 line beast. I prefer to keep the AppDelegate clean :-)
I'm using Apple's UIPageViewController template, which includes a "ModelController" class. I use this class to return individual pages in the form of a viewcontroller, but how much setup is the Model class responsible for? For example, I have a plist that contains an array of image layout info for each page. Should the model hold the entire array, and then set each viewcontroller with its specific layout information, or should each viewcontroller just get its own layout info? What exactly should the model take care of?
I would suggest to make the model as heavy as possible, and the viewcontoller as light as possible
Another thing is to use lazy initialization for the image in the viewcontollers
So ideally the model will contain the array of the names of all the images that you wish to load, and each time a new page is generated load the image and add it to the viewcontoller that you will create.
The viewcontroller will have all the information needed for it, this means that you could use this same viewcontoller as a stand alone controller outside of the context of pageviewcontroller
So the model will be only responsible to load the required variables,
the access to these files, the loading of the images will be done in the viewcontroller, in a way that viewcontroller will only receive strings as parameters, and the loading logic is done inside the viewcontoller, hence decoupling the views as much as you can