设计模式 - Objective-C - MVC 模型视图控制器

6

你好,我已经阅读了关于MVC的教程,并在这里阅读了相关主题。我认为我理解了MVC的概念,但我不确定如何实现它。

我尝试将其应用于一个简单的程序,一个带有标签和按钮的窗口。按钮增加计数器,标签显示其值。

我尝试了两种不同的方法。

在第一种情况下(示例有效),我将视图和控制器融合在一起。正如我所说,示例有效,但我想让你们告诉我,这是否是MVC的正确实现,或者它是否没有遵循正确的设计。

第二个示例将模型、视图和控制器作为三个分离的类,但该示例无法工作,因为V和C会相互导入,所以我希望你们告诉我我做错了什么。

第一个版本:模型、视图-控制器

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



这种方式是MVC的正确模式吗?代码可以运行,但在开始更复杂的应用程序之前,我想确保我以正确的方式编写它。这是我编写此应用程序的方式,我的MVC方式。它是好还是坏?如何改变或修复它?




第二个版本:模型、视图、控制器分离

----> 这是模型

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

----> 这是视图

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

----> 这是控制器(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



这个版本无法工作,因为视图和控制器之间互相引用,编译器会给出警告。

2个回答

27

简单来说:UIViewController 不是你的视图,它是你的控制器。

UIViewController 看作木偶师,UIView 看作木偶。

  • UIViewController 控制在 UIView 上显示什么。
  • UIView 的主要目的是包含子视图。
  • NSObject 可以被任何类使用,但应该由 UIViewController 使用。

http://www.codeschool.com/courses/try-ios。

让我们来分解一下:

注意:这里我们使用 @property 声明。这将为您节省编写自己的 setter 和 getter 方法的时间(除非您需要覆盖它们以进行自定义功能)。

NSObject(模型):

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

@interface MyModelObject : NSObject

@property (nonatomic) int count; 

@end

UIView(视图):

//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(控制器,所有的东西都在这里汇聚!):

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

3
2017年,我喜欢它:D。 - warzone_fz
2
它是2018年,我也喜欢这个! - user4913965
1
我们明年见。 - NSPratik
1
it's 2020 & i'm lovin it :D - Renata Faria
1
2021 年了,我喜欢它 :D - Muffins
显示剩余3条评论

1

对于那些对UI元素放置位置有疑惑的人,我通常喜欢把UI元素放在 View.m 中。

我的策略是将所有构建UI元素的方法放在View.m中,其中我有一个方法调用View.m中的所有其他方法。因此,在ViewController中只调用一个方法

例如:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接