【问题标题】:Design Pattern - Objective-C - MVC Model View Controller设计模式 - Objective-C - MVC 模型视图控制器
【发布时间】:2013-07-31 13:06:51
【问题描述】:

您好,我已经阅读了有关 MVC 的 Web 教程,并且已经阅读了此处的主题。我想我了解了 MVC 的概念,但我不确定它的实现。

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

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

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

第二个示例将模型视图和控制器作为 3 个分离的类,但该示例不起作用,因为 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.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



这个版本不起作用,因为类视图和控制器相互导入并且编译器给了我一个警告

【问题讨论】:

    标签: objective-c model-view-controller model design-patterns


    【解决方案1】:

    简单地说:UIViewController 不是您的视图,而是您的控制器

    UIViewController 想象成一个傀儡,把UIView 想象成傀儡。

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

    诚然,在完成 codeschool 的教程 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
    

    【讨论】:

    • 2017 年,我很喜欢:D
    • 现在是 2018 年,我也喜欢这个!
    • 2019年再见
    • 您好,从 2019 年开始! :D
    • 现在是 2020 年,我很喜欢:D
    【解决方案2】:

    对于那些对 UI 元素放在哪里有疑问的人,我经常喜欢将 UI 元素放在 View.m

    我的策略是让所有方法都在 View.m 中构建 UI 元素,其中我有一个方法可以调用 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
    
    

    【讨论】:

      猜你喜欢
      • 2012-02-12
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 2011-09-12
      • 2010-10-02
      • 2011-10-20
      • 2011-04-28
      • 1970-01-01
      相关资源
      最近更新 更多