Hi I already read tutorials around the web on MVC and already read the topics on here. I think i got the concept of the MVC but i'm not sure of its implementation.
I've tried to apply it to a simple program, a window that have a label and a button. The button increase a counter and the label shows the value of it.
I tried in 2 different ways.
In the first case ( the example works ) i melt the View and the Controller. As i said, the example works, but i want you guys to tell me if it's a correct implementation for MVC or it's not following the right design.
The second example has Model View and Controller as 3 separated class, but the example doesnt work because the V and the C import itself, so i would love you guys to tell me where i'm doing wrong.
first version: model, view-controller
//Model.h
#import <Foundation/Foundation.h>
@interface Model : NSObject {
int _counter;
}
-(void)setCounter:(int)valueCounter;
-(int)getCounter;
-(void)increaseCounter;
@end
//Model.m
#import "Model.h"
@implementation Model {}
-(void)setCounter:(int)valueCounter { _counter = valueCounter; }
-(int)getCounter { return _counter; }
-(void)increaseCounter{ _counter ++; }
@end
//ViewController.h
#import <UIKit/UIKit.h>
#import "Model.h"
@interface ViewController : UIViewController {
IBOutlet UIButton *_button;
IBOutlet UILabel *_label;
Model *myModel;
}
-(IBAction)send:(id)sender;
@end
//ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myModel = [[Model alloc]init];
_label.text = [NSString stringWithFormat:@"%d",[myModel getCounter]];
}
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; }
- (IBAction)send:(id)sender{
[myModel increaseCounter];
_label.text = [NSString stringWithFormat:@"%d",[myModel getCounter]];
}
@end
Is this way a correct Pattern for MVC ? The code works, but before i start more complex apps i want to make sure i code it in a good way. This is how i would do this app, my way of MVC. is it bad? good? how to change or fix it?
Second Version: Model, View, Controller separated
----> This is the Model
//Model.h
#import <Foundation/Foundation.h>
@interface Model : NSObject {
int _count;
}
-(void)setCount:(int)value;
-(int)getCount;
-(void)increaseCount;
@end
//Model.m
#import "Model.h"
@implementation Model
-(void)setCount:(int)value { _count = value; }
-(int)getCount { return _count; }
-(void)increaseCount { _count = _count++; }
@end
----> This is the View
//View.h
#import <UIKit/UIKit.h>
#import "Controller.h"
@interface ViewController : UIViewController{
IBOutlet UILabel *label;
IBOutlet UIButton *button;
Controller *myController;
}
@end
//View.m
#import "ViewController.h"
#import "Controller.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myController = [[Controller alloc]init];
}
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; }
-(IBAction)pressButton:(id)sender{
label.text = [NSString stringWithFormat:@"%d",[myController actionIncrease]];
}
@end
----> This is the Controller
//Controller.m
#import <Foundation/Foundation.h>
@class "Model.h"
@class "ViewController.h"
@interface Controller : NSObject {
Model *_mymodel;
UIViewController *_myviewController;
}
-(int)actionIncrease;
@end
//Controller.m
#import "Controller.h"
#import "Model.h"
@implementation Controller
-(id)init{
_mymodel = [[Model alloc]init];
}
-(int)actionIncrease {
[_mymodel increaseCount];
return [_mymodel getCount];
}
@end
this version doesn't work because the classes view and controller import each other and the compiler gives me a warning
In the MVC design pattern, the view and the controller makes use of strategy design and the view and the model are synchronized using the observer design. Hence, we may say that MVC is a compound pattern. The controller and the view are loosely coupled and one controller can be used by multiple views.
The Model-View-Controller (MVC) is an architectural pattern which separates an application into three main groups of components: Models, Views, and Controllers. MVC is abbreviated as Model View Controller is a design pattern created for developing applications specifically web applications.
In MVC, the controller is the entry point to the Application, while in MVVM, the view is the entry point to the Application. MVC Model component can be tested separately from the user, while MVVM is easy for separate unit testing, and code is event-driven.
Simply: UIViewController
is not your view, it's your controller
UIViewController
as a puppeteer and the UIView
as the puppet.UIViewController
controls WHAT is displayed on the UIViewUIView
's main purpose is to contain subviews.NSObject
can be used by any class, but should be used by the UIViewController
.Admittedly, I understood it much better after completing codeschool's tutorial http://www.codeschool.com/courses/try-ios. I highly recommend this simple hands-on approach.
Let's break it down:
Note: Here we utilize @property
declarations instead. These will save you from writing your own setter and getter methods. (unless you need to override them for custom functionality)
//MyModelObject.h
#import <Foundation/Foundation.h>
@interface MyModelObject : NSObject
@property (nonatomic) int count;
@end
//MyView.h
#import <UIKit/UIKit.h>
@interface MyView : UIView
// holds it's own subviews
@property (strong, nonatomic) UIView *anotherView;
@property (strong, nonatomic) UIImageView *myImageView;
@end
//MyViewController.h
#import <Foundation/Foundation.h>
#import "MyView.h" // your custom view
#import "MyModel.h" // your custom model
@interface MyViewController : UIViewController
@property (strong, nonatomic) MyView *myView
// see how the view is "owned" by the view controller?
@end
//MyViewController.m
@implementation MyViewController
@synthesize myView;
- (void) someMethod {
[myView doSomething];
}
@end
For whose have any doubt about where put the UI elements, I often like put the UI elements in View.m
My strategy is make all methods to build UI elements in View.m, where I have a method that call all others methods in View.m. Thus, i call only one method in ViewController
For example :
TodayView.h
#import <UIKit/UIKit.h>
@interface TodayView : UIView
@property (strong, nonatomic) UIImageView *imageView;
@property (strong,nonatomic) UINavigationBar *navBar;
-(void) addAllElements:(UIView*) mainView addController:(UIViewController*) controller;
-(void) addImage:(UIImageView*) image view:(UIView*) todayView;
-(void) addNavBar:(UIViewController*) navController addView:(UIView*)view;
@end
TodayView.m
#import "TodayView.h"
@implementation TodayView
-(void) addImage:(UIImageView *)image view:(UIView *)todayView{
image= [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
image.image = [UIImage imageNamed:@"icone-apps"];
[todayView addSubview:image];
}
-(void) addNavBar:(UIViewController *)navController addView:(UIView *)view{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, 120, 50)];
label.textAlignment = UITextAlignmentCenter;
[label setFont:[UIFont boldSystemFontOfSize:40.0]];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor blackColor]];
[label setText:@"Hoje"];
[navController.navigationController.navigationBar.topItem setTitleView:label];
[view addSubview:label];
}
-(void) addAllElements:(UIView *)mainView addController:(UIViewController*)controller{
[self addNavBar:controller addView:mainView];
}
@end
TodayViewController.m
#import "TodayViewController.h"
@interface TodayViewController ()
@end
@implementation TodayViewController
@synthesize myView;
-(void) blankMethod{
}
-(void) addImage:(TodayView*)todayView{
todayView.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
todayView.imageView.image = [UIImage imageNamed:@"icone-apps"];
[self.view addSubview:todayView.imageView];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
TodayView *todayView = [[ TodayView alloc] init];
# Here I call the method that call all others methods to build UI elements
[todayView addAllElements:self.view addController:self];
}
-(UITabBarItem*) tabBarItem{
return [[UITabBarItem alloc] initWithTitle:@"Hoje" image:[UIImage imageNamed:@"icone-hoje"] tag:0];
}
@end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With