专业java、php、iOS、C++、网页设计、平面设计、网络营销、游戏开发、前端与移动开发培训机构

使用菜单项模型和视图模型

  • 定义 CZMenuItem 模型,用于存储每个按钮的数据

    • CZMenuItem.h

        @interface CZMenuItem : NSObject
      
        /// 标题
        @property (nonatomic, strong) NSString *title;
      
        + (instancetype)menuItemWithDict:(NSDictionary *)dict;
      
        @end
      
    • CZMenuItem.m

        #import "CZMenuItem.h"
      
        @implementation CZMenuItem
      
        + (instancetype)menuItemWithDict:(NSDictionary *)dict {
            id obj = [[CZMenuItem alloc] init];
      
            [obj setValuesForKeysWithDictionary:dict];
      
            return obj;
        }
        @end
      
  • CZMenuViewController 中将字典转成模型

      /// 设置composeView
      - (void)prepareComposeView {
          [self.view addSubview:self.composeView];
    
          [self.composeView mas_makeConstraints:^(MASConstraintMaker *make) {
              make.leading.bottom.trailing.equalTo(self.view);
              make.height.equalTo(@90);
          }];
    
          self.composeView.distribution = UIStackViewDistributionFillEqually;
    
          NSArray *items = @[
                             @{@"title": @"写说说"},
                             @{@"title": @"发照片"},
                             @{@"title": @"写日志"}];
    
          NSMutableArray *composeItems = [NSMutableArray array];
          // 字典转模型
          for (NSDictionary *dict in items) {
              CZMenuItem *item = [CZMenuItem menuItemWithDict:dict];
              [composeItems addObject:item];
          }
    
          for (CZMenuItem *item in composeItems) {
              UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
              [button setTitle:item.title forState:UIControlStateNormal];
              button.backgroundColor = [UIColor randomColor];
    
              [self.composeView addArrangedSubview:button];
          }
      }
    
      - (void)prepareMenuView {
          [self.view addSubview:self.menuView];
    
          [self.menuView mas_makeConstraints:^(MASConstraintMaker *make) {
              make.leading.trailing.equalTo(self.view);
              make.bottom.equalTo(self.composeView.mas_top);
          }];
    
          self.menuView.axis = UILayoutConstraintAxisVertical;
    
          NSArray *items = @[@{@"title": @"全部动态"},
                             @{@"title": @"与我相关"},
                             @{@"title": @"照片墙"},
                             @{@"title": @"电子相框"},
                             @{@"title": @"好友"},
                             @{@"title": @"更多"}];
    
          NSMutableArray *menuItems = [NSMutableArray array];
          // 字典转模型
          for (NSDictionary *dict in items) {
              CZMenuItem *item = [CZMenuItem menuItemWithDict:dict];
              [menuItems addObject:item];
          }
    
          for (CZMenuItem *item in menuItems) {
              UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
              button.backgroundColor = [UIColor randomColor];
              [button setTitle:item.title forState:UIControlStateNormal];
    
              [button mas_makeConstraints:^(MASConstraintMaker *make) {
                  make.height.equalTo(@(MenuButtonHeight));
              }];
    
              [self.menuView addArrangedSubview:button];
          }
      }
    
  • 发现在控制器处理字典转模型,控制器负责的事情太多 .导致控制器代码臃肿.不利于维护
  • 定义 CZMenuItemViewModel, 负责处理 CZMenuItem 模型的相关操作

    • CZMenuItemViewModel.h,定义 撰写按钮模型数组 composeItems菜单模型数组 menuItems

        @interface CZMenuItemViewModel : NSObject
      
        /// 撰写按钮模型数组
        @property (nonatomic, strong) NSArray *composeItems;
      
        /// 菜单模型数组
        @property (nonatomic, strong) NSArray *menuItems;
        @end
      
    • CZMenuItemViewModel.m

        #import "CZMenuItemViewModel.h"
        #import "CZMenuItem.h"
      
        @implementation CZMenuItemViewModel
      
        - (NSArray *)composeItems {
            if (_composeItems == nil) {
                NSMutableArray *array = [[NSMutableArray alloc] init];
      
                NSArray *items = @[@{@"title": @"说说"},
                                   @{@"title": @"照片"},
                                   @{@"title": @"日志"}];
      
                for (NSDictionary *dict in items) {
                    CZMenuItem *item = [CZMenuItem menuItemWithDict:dict];
      
                    [array addObject:item];
                }
      
                _composeItems = array;
            }
      
            return _composeItems;
        }
      
        - (NSArray *)menuItems {
            if (_menuItems == nil) {
                NSMutableArray *array = [[NSMutableArray alloc] init];
      
                NSArray *items = @[@{@"title": @"全部动态"},
                                   @{@"title": @"与我相关"},
                                   @{@"title": @"照片墙"},
                                   @{@"title": @"电子相框"},
                                   @{@"title": @"好友"},
                                   @{@"title": @"更多"}];
      
                for (NSDictionary *dict in items) {
                    CZMenuItem *item = [CZMenuItem menuItemWithDict:dict];
                    [array addObject:item];
                }
      
                _menuItems = array;
            }
      
            return _menuItems;
        }
        @end
      
  • CZMenuViewController 中懒加载 CZMenuItemViewModel

    • @interface CZMenuViewController

        @interface CZMenuViewController ()
      
        /// iPhone界面的容器视图
        @property (weak, nonatomic) UIView *containerView;
      
        /// 底部撰写视图(包含3个按钮)
        @property (nonatomic, strong) UIStackView *composeView;
      
        /// 菜单按钮
        @property (nonatomic, strong) UIStackView *menuView;
      
        /// 菜单项模型数组
        @property (nonatomic, strong) CZMenuItemViewModel *menuItemVM;
      
        @end
      
    • @implementation CZMenuViewController

        - (CZMenuItemViewModel *)menuItemVM {
            if (_menuItemVM == nil) {
                _menuItemVM = [[CZMenuItemViewModel alloc] init];
            }
      
            return _menuItemVM;
        }
      
  • 使用 menuItemVM 来提供模型数据

      - (void)prepareComposeView {
          // 将stackView添加到self.view
          [self.view addSubview:self.composeView];
    
          // stackView添加约束
          [self.composeView mas_makeConstraints:^(MASConstraintMaker *make) {
              // 左右底部和self.view对齐
              make.leading.trailing.bottom.equalTo(self.view);
              make.height.equalTo(@(ComposeViewLnadscapeHeight));
          }];
    
          // 设置stackView布局方式
          self.composeView.distribution = UIStackViewDistributionFillEqually;
    
          for (CZMenuItem *item in self.menuItemVM.composeItems) {
              // stackView添加子控件
              UIButton *button = [[UIButton alloc] init];
    
              button.backgroundColor = [UIColor randomColor];
    
              [button setTitle:item.title forState:UIControlStateNormal];
    
              [self.composeView addArrangedSubview:button];
          }
      }
    
      - (void)prepareMenuView {
          // 将stackView添加到self.view
          [self.view addSubview:self.menuView];
    
          // stackView添加约束,不指定布局方向的尺寸stackView会根据子控件的内容来自动约束
          [self.menuView mas_makeConstraints:^(MASConstraintMaker *make) {
              // 左右和self.view对齐
              make.leading.right.equalTo(self.view);
    
              // 底部和composeView的顶部对齐
              make.bottom.equalTo(self.composeView.mas_top);
          }];
    
          // 设置布局方向
          self.menuView.axis = UILayoutConstraintAxisVertical;
    
          for (CZMenuItem *item in self.menuItemVM.menuItems) {
              // stackView添加子控件
              UIButton *button = [[UIButton alloc] init];
    
              button.backgroundColor = [UIColor randomColor];
    
              [button setTitle:item.title forState:UIControlStateNormal];
    
              // 设置按钮的高度
              [button mas_makeConstraints:^(MASConstraintMaker *make) {
                  make.height.equalTo(@(MenuButtonHeight));
              }];
    
              [self.menuView addArrangedSubview:button];
          }
      }
    
  • CZMenuItemViewModel.h 中的 composeItemsmenuItems 属性只需要让别人来读取就可以了,不要让别人可以修改,修改代码添加 readonly 修饰符

      @interface CZMenuItemViewModel : NSObject
    
      /// 撰写按钮模型数组, 外界只读
      @property (nonatomic, strong, readonly) NSArray *composeItems;
    
      /// 菜单模型数组, 外界只读
      @property (nonatomic, strong, readonly) NSArray *menuItems;
      @end
    
  • 由于我们给属性添加了 readonly, Xcode 并不会自动添加 _属性名 的成员变量,需要使用 @synthesize 来指定 属性 对应的成员变量,在 @implementation CZMenuItemViewModel 中添加:
    @synthesize composeItems = _composeItems;
    @synthesize menuItems = _menuItems;