当前位置:   article > 正文

[iOS开发]MVC模式的学习_ios multiple mvc

ios multiple mvc

一、MVC的概念
MVC是Model-VIew-Controller,就是模型-视图-控制器,MVC把软件系统分为三个部分:Model,View,Controller。其就是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑

Model(模型对象):
模型对象封装了应用程序的数据,并定义操控和处理该数据的逻辑和运算。就是比如游戏中的角色本身属性的数值,当游戏中的本身角色属性更改时(例如通过网络连接接收到了新的数据或者游戏中的成长数值属性造成了属性数据的更改),模型对象的更改,通知控制器对象,控制器对象更新相应的视图对象,这就是一套完整的流程。

View(视图对象):
视图对象是应用程序中用户可以看见的对象。在iOS应用程序开发中,所有的控件、窗口等都继承自 UIView,对应MVC中的V。UIView及其子类主要负责UI的实现,而UIView所产生的事件都可以采用委托的方式,交给UIViewController实现。

Controller(控制器对象):
控制器对象解释在视图对象中进行的用户操作,并将新的或更改过的数据传达给模型对象。模型对象更改时,一个控制器对象会将新的模型数据传达给视图对象,以便视图对象可以显示它。
对于不同的UIView,有相应的UIViewController,对应MVC中的C。例如在iOS上常用的UITableView,它所对应的Controller就是UITableViewController。

二、MVC之间的交流模式
在这里插入图片描述

1 Controller与View之间可以进行交流,Controller可以通过outlet去控制View(输出口:控制器类可以通过一种特殊的属性来引用nib文件中的对象,可以把输出口看成是指向需要的对象的指针),而View通过,delegate,data source,target-action 来和Controller进行通信。

2 Controller在接收到View传过来的Button的点击事件 经过判断处理后,可以选择下一步的具体操作过程,比如弹窗或者新界面的弹出。也可以交给Model处理,方法就是设置一个代理,从C将V传递的值再传递给M(比如在Model中通过判断后发布通知是否需要,Model在处理完数据之后,有时候可能会通过通知或者kvo的方式告知Controller,Model只负责通知,之后的操作由Controller决定)

3 Model不允许与View打交道

三、登陆注册demo

  • 首先应该创建M V C三个文件夹(需要几个view创建几套文件夹)
  • 新建一个LandModel的类,继承自NSObject
  • LandView的类,继承自UIView
  • LandController的类,继承自UIViewController
    在这里插入图片描述

首先看LandView的代码,按照MVC模式来说 视图对象是应用程序中用户可以看见的对象,所以在view中声明两个UITextField和UIButton 输入框和登陆注册按钮 并且确定展示的位置与内容、颜色等等细节。

LandView.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface LandView : UIView

@property(nonatomic,strong)UITextField *nameTextField;
@property(nonatomic,strong)UITextField *passTextField;
@property(nonatomic,strong)UIButton *landButton;
@property(nonatomic,strong)UIButton *registerButton;

@end

NS_ASSUME_NONNULL_END

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

LandView.m 注意在.m文件中重写了init函数 原因:
(
什么时候用initWithFrame方法?
简单的说,我们用编程方式申明,创建UIView对象时,使用initWithFrame方法。

在此,我们必须搞清楚,两种方式来进行初始化UIView。

1.使用 Interface Builder 方式。
这种方式,就是使用nib文件。通常我们说的“拖控件” 的方式。
实际编程中,我们如果用Interface Builder 方式创建了UIView对象。(也就是,用拖控件的方式)
那么,initWithFrame方法方法是不会被调用的。因为nib文件已经知道如何初始化该View。(因为,我们在拖该view的时候,就定义好了长、宽、背景等属性)。
这时候,会调用initWithCoder方法,我们可以用initWithCoder方法来重新定义我们在nib中已经设置的各项属性。

2.使用编程方式。
就是我们声明一个UIView的子类,进行“手工”编写代码的方式。
实际编程中,我们使用编程方式下,来创建一个UIView或者创建UIView的子类。这时候,将调用initWithFrame方法,来实例化UIView。
特别注意,如果在子类中重载initWithFrame方法,必须先调用父类的initWithFrame方法。在对自定义的UIView子类进行初始化操作。)

#import "LandView.h"

@implementation LandView

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    self.backgroundColor = [UIColor whiteColor];
    _nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 175, 50)];
    _nameTextField.placeholder = @"输入用户名";
    [self addSubview:_nameTextField];
    
    _passTextField = [[UITextField alloc] initWithFrame:CGRectMake(100, 300, 175, 50)];
    _passTextField.placeholder = @"输入密码";
    [self addSubview:_passTextField];
    
    _landButton= [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_landButton setTitle:@"登陆" forState:UIControlStateNormal];
    [_landButton setFrame:CGRectMake(120, 500, 75, 30)];
    [self addSubview:_landButton];
    
    _registerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_registerButton setTitle:@"注册" forState:UIControlStateNormal];
    [_registerButton setFrame:CGRectMake(225, 500, 75, 30)];
    [self addSubview:_registerButton];
    
    return self;
}

@end

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

其次看LandController文件 一开始两个landView和landModel就是outlet输出口 上面已经解释过,同时我将view和controller的target-action写在了c中,通过一个flag来判断是否与Model中的用户名和密码是否一致。在按下注册按钮时,同时将此时Model中的两个数组传递到注册界面,防止重复注册。

//
//  LandController.m
//  MVC-
//
//  Created by young_jerry on 2020/9/14.
//  Copyright © 2020 young_jerry. All rights reserved.
//

#import "LandController.h"
#import "LandView.h"
#import "LandModel.h"
#import "RegisterController.h"

@interface LandController ()<RegisterDelegate>
@property(nonatomic,assign) NSInteger flag;
@property(nonatomic,strong) LandView *landView;
@property(nonatomic,strong) LandModel *landModel;

@end

@implementation LandController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    _landView = [[LandView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    
    [_landView.registerButton addTarget:self action:@selector(pressRegister) forControlEvents:UIControlEventTouchUpInside];
    [_landView.landButton addTarget:self action:@selector(pressLand) forControlEvents:UIControlEventTouchUpInside];
    
    _landModel = [[LandModel alloc]init];
    [_landModel landModelInit ];
    
    [self.view addSubview:_landView];
}

-(void)pressRegister{
    
    RegisterController *registerView = [[RegisterController alloc]init];
    
    registerView.modalPresentationStyle = UIModalPresentationFullScreen;
    
    registerView.registerDelegate = self;
    
    registerView.nametempMutArray = _landModel.nameStr;
    
    registerView.passtempMutArray = _landModel.passStr;
    
    [self presentViewController:registerView animated:YES completion:nil];
}

-(void)pressLand{
    for(int i = 0; i < _landModel.nameStr.count; i++){
    
        if ( [_landModel.nameStr[i] isEqualToString: _landView.nameTextField.text ] && [_landModel.passStr[i] isEqualToString: _landView.passTextField.text]){
            _flag = 1;
        }
    }
    if(_flag == 1){
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"登陆正确!" preferredStyle:UIAlertControllerStyleAlert];
           
            UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
        
            [alert addAction:sure];
        
            [self presentViewController:alert animated:NO completion:nil];
    }else{
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"登陆错误!" preferredStyle:UIAlertControllerStyleAlert];

            UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];

            [alert addAction:sure];

            [self presentViewController:alert animated:NO completion:nil];
    }
    _flag = 0;
}
- (void)passName:(NSString *)name passPass:(NSString *)pass{
    _landView.nameTextField.text = name;
    [_landModel.nameStr addObject:name];
    
    _landView.passTextField.text = pass;
    [_landModel.passStr addObject:pass];
}

@end






  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

Model界面
.h:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LandModel : NSObject
@property(nonatomic,copy)NSMutableArray *nameStr;
@property(nonatomic,copy)NSMutableArray *passStr;
-(void)landModelInit;
@end

NS_ASSUME_NONNULL_END

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

.m:

#import "LandModel.h"

@implementation LandModel
-(void)landModelInit{
    _nameStr = [[NSMutableArray alloc]init];
    _passStr = [[NSMutableArray alloc]init];
    [_nameStr addObject:@"111"];
    [_passStr addObject:@"111"];
}
@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注册界面的view和controller和登陆界面差不多,多了个传值。
下面是注册的controller界面:


#import "RegisterController.h"
#import "RegisterView.h"
#import "RegisterModel.h"

@interface RegisterController ()

@property(nonatomic,strong) RegisterView *registerView;
@property(nonatomic,strong) RegisterModel *registerModel;

@property(nonatomic,assign) NSInteger flag;

@end

@implementation RegisterController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    _registerView = [[RegisterView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [_registerView.relandButton addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_registerView];
    
//    NSLog(@"%@",_nametempMutArray);
    
    
}
-(void)press{
    for (int i = 0; i < _nametempMutArray.count; i++) {
          if([_registerView.renameTextField.text isEqualToString:_nametempMutArray[i]]){
              _flag = 1;
            }
    }
    if(_flag == 1){
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"用户名重复!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
        [alert addAction:sure];
        [self presentViewController:alert animated:NO completion:nil];
           
    }else{
        
        [_registerDelegate passName:_registerView.renameTextField.text passPass:_registerView.repassTextField.text];
        [self dismissViewControllerAnimated:YES completion:nil];
    
   
    }
    _flag = 0;
}

@end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/882401
推荐阅读
相关标签
  

闽ICP备14008679号