Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design Pattern - Objective-C - MVC Model View Controller

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

like image 593
mystudioos Avatar asked Jul 31 '13 13:07

mystudioos


People also ask

What design pattern does MVC use?

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.

Is Model View Controller a design pattern?

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.

What is difference between MVC and MVVM?

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.


2 Answers

Simply: UIViewController is not your view, it's your controller

Think of the UIViewController as a puppeteer and the UIView as the puppet.

  • UIViewController controls WHAT is displayed on the UIView
  • UIView'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)

NSObject (model):

//MyModelObject.h
#import <Foundation/Foundation.h>

@interface MyModelObject : NSObject

@property (nonatomic) int count; 

@end

UIView (view):

//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

UIViewController (controller, it all comes together here!):

//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
like image 164
Mike Rapadas Avatar answered Oct 16 '22 08:10

Mike Rapadas


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

like image 39
mkilmer Avatar answered Oct 16 '22 07:10

mkilmer