• iOS_21团购_顶部菜单和弹出菜单联动


    最后效果图:






    各控件关系图1:



    各控件关系图2:



    点击Dock上面的buttonDockItem,

    创建经导航控制器包装的DealListController,

    而且加入到主控制器的右側空间

    //
    //  DealListController.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-14.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击dock上面的【团购】button相应的控制器,上面是导航栏,导航栏右边是searchBar,导航栏左边是一个大button(TopMenu)(内部由三个小button组成<TopMenuItem>)
    
    #import "DealListController.h"
    // 导航栏左边是一个大button(顶部菜单)
    #import "TopMenu.h"
    
    @interface DealListController ()
    
    @end
    
    @implementation DealListController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 1,设置上方的导航栏,右边是搜索bar,左边是一个大的VIEW(内有三个button),即TopMenu,内部的button是TopMenuItem
        [self addNaviBarBtn];
        
    }
    // 1,设置上方的导航栏,右边是搜索bar,左边是一个大的VIEW(内有三个button),<span style="font-family: Arial, Helvetica, sans-serif;">即TopMenu,内部的button是TopMenuItem</span>
    - (void)addNaviBarBtn
    {
    
        
        // 1.右边的搜索框
        UISearchBar *s = [[UISearchBar alloc] init];
        s.frame = CGRectMake(0, 0, 210, 35);
        s.placeholder = @"请输入商品名、地址等";
        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:s];
        
        // 2.左边的菜单条,导航栏左边是一个大button(顶部菜单)
        TopMenu *topMenu = [[TopMenu alloc] init];
        // 3.用于点击顶部button时,容纳创建出来的底部弹出菜单(包含一个contentView和cover,contentView又包含scrollView和subTitleImgView),本成员是由创建此TopMenu的外部赋值传入, 这里是控制器的view,就是导航栏以下的全部区域
        // 重要~~~~~~~~~~
        topMenu.controllerView = self.view;
    
        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:topMenu];
    }
    @end

    TopMenu.h

    //
    //  TopMenu.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击dock上面的【团购】button时,创建出相应的经导航包装后的子控制器,子控制器的上面是导航栏,导航栏右边是searchBar,导航栏左边是一个大button(TopMenu)(内部仅仅由三个小button组成<TopMenuItem>它们各自是:所有频道,所有商区,默认排序),点击TopMenu中的某一个button<TopMenuItem>,会在其下方,弹出一个PopMenu,PopMenu包含二个部分(上面是一个contentView:包含:scrollView和subTitleImgView,下:蒙板)
    
    #import <UIKit/UIKit.h>
    
    @interface TopMenu : UIView
    
    
    //  用于点击顶部菜单项时,容纳创建出来的底部弹出菜单(包含一个contentView和cover,contentView又包含scrollView和subTitleImgView),本成员是由创建此TopMenu的控制器赋值传入, 本成员属性是用来接收控制器的view,就是导航栏以下的所有区域,目的是用于加入并展示PopMenu
    @property (nonatomic, weak) UIView *controllerView;
    @end
    


    TopMenu.m


    负责创建和加入3个TopMenuItem,

    监听其内部三个TopMenuItem的点击事件,

    而且依据点击的button的tag不同,创建出不同的PopMenu,并控制PopMenu的出现和隐藏,最后一个是注冊到通知中心,监听全部通知,而且设置三个TopMenuItem的显示文字



    //
    //  TopMenu.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击dock上面的【团购】button相应的控制器,上面是导航栏,导航栏右边是searchBar,导航栏左边是一个大button(TopMenu)(内部仅仅由三个小button组成<TopMenuItem>它们各自是:所有频道,所有商区,默认排序),点击TopMenu中的某一个button<TopMenuItem>,会在其下方,弹出一个PopMenu,PopMenu包含二个部分(上面是一个contentView:包含:scrollView和subTitleImgView,下:蒙板)
    
    #import "TopMenu.h"
    
    
    #import "TopMenuItem.h"
    #import "CategoryPopMenu.h"
    #import "DistrictPopMenu.h"
    #import "OrderPopMenu.h"
    #import "MetaDataTool.h"
    #import "Order.h"
    
    @interface TopMenu()
    {
        // 三个顶部菜单项中当前选中的那一个,三个button:所有分类,所有商区,默认排序
        TopMenuItem *_currentTopMenuItem;
        
        
        
    // 在点击不同的顶部菜单项的时候,由于要控制其相应的底部弹出菜单的出现和隐藏,因此,在创建它时,就要用成员变量,记住 弹出的分类菜单
        CategoryPopMenu *_categoryPopMenu;
    // 在点击不同的顶部菜单项的时候,由于要控制其相应的底部弹出菜单的出现和隐藏,因此,在创建它时,就要用成员变量,记住 弹出的区域菜单
        DistrictPopMenu *_districtPopMenu;
    // 在点击不同的顶部菜单项的时候,由于要控制其相应的底部弹出菜单的出现和隐藏,因此,在创建它时,就要用成员变量,记住 弹出的排序菜单
        OrderPopMenu *_orderPopMenu;
        
        
    // 正在展示的底部弹出菜单,是个父类
        PopMenu *_showingPopMenu;
        
        
        
    
        // 由于要更改其显示文字,所以要成员变量记住创建出来的 分类菜单项
        TopMenuItem *_categoryTopMenuItem;
        // 由于要更改其显示文字,所以要成员变量记住创建出来的 区域菜单项
        TopMenuItem *_districtTopMenuItem;
        // 由于要更改其显示文字,所以要成员变量记住创建出来的 排序菜单项
        TopMenuItem *_orderTopMenuItem;
    }
    @end
    
    
    @implementation TopMenu
    
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            
            // 1.加入一个button:所有分类 (由于要更改其显示文字,所以要成员变量记住)
            _categoryTopMenuItem = [self addMenuItem:kAllCategory index:0];
            
            // 2.加入一个button:所有商区 (由于要更改其显示文字,所以要成员变量记住)
            _districtTopMenuItem = [self addMenuItem:kAllDistrict index:1];
            
            // 3.加入一个button:默认排序 (由于要更改其显示文字,所以要成员变量记住)
            _orderTopMenuItem = [self addMenuItem:@"默认排序" index:2];
            
            // 4.顶部菜单须要注冊并监听所有通知,目的是更改其里面菜单项的文字,而且控制弹出菜单的显示和隐藏
            kAddAllNotes(dataChange)
        }
        return self;
    }
    // 5,抽取的方法,加入一个顶部菜单项(TopMenuItem),三个button:所有分类,所有商区,默认排序
    - (TopMenuItem *)addMenuItem:(NSString *)title index:(int)index
    {
        TopMenuItem *item = [[TopMenuItem alloc] init];
        item.title = title;
        item.tag = index;
        // 三个button:所有分类,所有商区,默认排序  水平排列
        item.frame = CGRectMake(kTopMenuItemW * index, 0, 0, 0);
        // 重要~~~顶部button(三个button:所有分类,所有商区,默认排序)被点击之后,都会调用此方法,依据tag进行区分,以便弹出不同的PopMenu
        [item addTarget:self action:@selector(topMenuItemClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:item];
        return item;
    }
    
    // 4.注冊并监听所有通知时调用此方法,更改button的文字,控制弹出菜单显示和隐藏
    - (void)dataChange
    {
        // 0.取消当前TopMenuItem的选中状态,而且置空_currentTopMenuItem ,由于监听到通知时,肯定是用户点击了一个子标题button,或者一个没有子标题的PopMenuItem
        _currentTopMenuItem.selected = NO;
        _currentTopMenuItem = nil;
        
        // 1.设置 分类button 要显示的文字,从工具中获得
        NSString *c = [MetaDataTool sharedMetaDataTool].currentCategoryName;
        if (c) {
            _categoryTopMenuItem.title = c;
        }
        
        // 2.设置 商区button 要显示的文字,从工具中获得
        NSString *d = [MetaDataTool sharedMetaDataTool].currentDistrictName;
        if (d) {
            _districtTopMenuItem.title = d;
        }
        
        // 3.设置 排序button 要显示的文字,从工具中获得
        NSString *o = [MetaDataTool sharedMetaDataTool].currentOrder.name;
        if (o) {
            _orderTopMenuItem.title = o;
        }
        
        // 4.最后,调用正在显示的弹出菜单的方法:隐藏底部弹出菜单,并置空正在显示的弹出菜单
        [_showingPopMenu hidePopMenu];
        _showingPopMenu = nil;
    }
    
    
    
    // 5-1,重要~~~监听顶部菜单项的点击,
    // 顶部button(三个button:所有分类,所有商区,默认排序)被点击之后,都会调用此方法,依据tag进行区分,以便弹出不同的PopMenu
    - (void)topMenuItemClick:(TopMenuItem *)item
    {
        // 0.假设还没有选择好城市,则不同意点击顶部菜单button
        if ([MetaDataTool sharedMetaDataTool].currentCity == nil) return;
        // 1.控制选中状态的切换,先把前面记住的当前顶部菜单项取消选中
        _currentTopMenuItem.selected = NO;
        // 假设两次点击的是同一个顶部菜单项,则隐藏掉弹出的菜单,而且置空当前的选中TopMenuItem
        if (_currentTopMenuItem == item) {
            _currentTopMenuItem = nil;
            // 隐藏底部菜单
            [self hidePopMenu];
        } else {
            // 假设两次点击的是是不同的顶部菜单项,将TopMenuItem置为选中状态,且用成员变量记住,而且展示相应的底部弹出菜单
            item.selected = YES;
            _currentTopMenuItem = item;
            // 显示与顶部菜单项,相应的底部弹出菜单
            [self showPopMenu:item];
        }
    }
    // 5-2,点击了同样的TopMenuItem,要隐藏底部已经弹出的菜单,而且置其为空
    - (void)hidePopMenu
    {
        // 调用_showingPopMenu其自己的方法,隐藏并移除其内部的contentView(包含scrollView和subTitleImgView,并置cover透明),并置空_showingPopMenu
        [_showingPopMenu hidePopMenu];
        _showingPopMenu = nil;
    }
    
    // 5-3,点击了不同的TopMenuItem,要显示相应的底部弹出菜单
    - (void)showPopMenu:(TopMenuItem *)item
    {
        // 1,先推断 是否须要让弹出菜单运行出场动画(没有正在展示的弹出菜单时,才须要运行出场动画)
        BOOL animted;
        // 假设有正在显示的弹出菜单,如切换button点击的时候
        if (_showingPopMenu) {
            // 1-1,先移除当前正在显示的弹出菜单
            [_showingPopMenu removeFromSuperview];
            // 1-2,不要动画出场
            animted = NO;
        }else{
            // 没有正在展示的弹出菜单时,才须要运行出场动画
            animted = YES;
        }
        
        // 2,依据点击的顶部菜单项的tag,创建并显示不同的底部弹出菜单(三个button:所有分类,所有商区,默认排序)
        if (item.tag == 0) {
            // 创建分类弹出菜单,而且用成员记住,且置其为正在展示的PopMenu
            if (_categoryPopMenu == nil) {
                _categoryPopMenu = [[CategoryPopMenu alloc] init];
            }
            _showingPopMenu = _categoryPopMenu;
        } else if (item.tag == 1) { // 区域
            // 创建商区弹出菜单,而且用成员记住,且置其为正在展示的PopMenu
            if (_districtPopMenu == nil) {
                _districtPopMenu = [[DistrictPopMenu alloc] init];
            }
            _showingPopMenu = _districtPopMenu;
        } else {
            // 创建 排序弹出菜单,而且用成员记住,且置其为正在展示的PopMenu
            if (_orderPopMenu == nil) {
                _orderPopMenu = [[OrderPopMenu alloc] init];
            }
            _showingPopMenu = _orderPopMenu;
        }
        
        // 创建出来相应的底部弹出菜单后,就要设置_showingPopMenu   的frame
        // _showingPopMenu.frame = _controllerView.bounds;
        
        // PopMenu 占领导航栏以下所有的空间
        _showingPopMenu.frame = (CGRect){0,kTopMenuItemH-1,_controllerView.bounds.size.width,_controllerView.bounds.size.height- kTopMenuItemH};
        
        
        
        // 设置创建出来的PopMenu的block回调,传递的是XXXPopMenu隐藏后,顶部菜单要做的事情如更改顶部的TopMenu的button选中状态
        __unsafe_unretained TopMenu *menu = self;
        _showingPopMenu.hideBlock = ^{
            // 重要~~~当_showingPopMenu隐藏后,要更改顶部的TopMenu的button选中状态
            
            // 1.取消当前的TopMenuItem的选中状态,并置空
            menu->_currentTopMenuItem.selected = NO;
            menu->_currentTopMenuItem = nil;
            
            // 2._showingPopMenu隐藏后,就要清空_showingPopMenu
            menu->_showingPopMenu = nil;
        };
        
        // 加入创建出来的即将要显示的弹出菜单 到_controllerView(即导航栏以下的所有空间都是弹出菜单的)
        [_controllerView addSubview:_showingPopMenu];
        
        // 运行刚才创建出来的底部弹出菜单的 出场动画,注意:仅仅有没有正在展示的弹出菜单时,才须要运行出场动画)
        if (animted) {
            [_showingPopMenu showPopMenu];
        }
    }
    
    
    
    // 顶部菜单宽度固定是三个button的宽高,由于仅仅有三个button:所有分类,所有商区,默认排序
    - (void)setFrame:(CGRect)frame
    {
        frame.size = CGSizeMake(3 * kTopMenuItemW, kTopMenuItemH);
        [super setFrame:frame];
    }
    // 顶部菜单由于要改变其三个button的文字,因此在通知中心注冊成为了监听者,因此dealloc时要在通知中心,移除掉监听者
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    @end
    


    TopMenuItem 顶部菜单项button

    //
    //  TopMenuItem.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击dock上面的【团购】button相应的控制器,上面是导航栏,导航栏右边是searchBar,导航栏左边是一个大button(TopMenu)(内部仅仅由三个小button组成<TopMenuItem>它们各自是:所有频道,所有商区,默认排序),点击TopMenu中的某一个button<TopMenuItem>,会在其下方,弹出一个PopMenu,PopMenu包含二个部分(上面是一个contentView:包含:scrollView和subTitleImgView,下:蒙板)
    
    
    
    
    
    
    #import <UIKit/UIKit.h>
    
    @interface TopMenuItem : UIButton
    // 设置buttonTopMenuItem显示的文字
    @property (nonatomic, copy) NSString *title;
    @end
    
    
    // 左文字 如所有分类 、所有商区、默认排序
    #define kTitleScale 0.8
    @implementation TopMenuItem
    
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 1.文字颜色
            [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            self.titleLabel.textAlignment = NSTextAlignmentCenter;
            self.titleLabel.font = [UIFont systemFontOfSize:15];
            
            // 2.设置button右边的箭头
            [self setImage:[UIImage imageNamed:@"ic_arrow_down.png"] forState:UIControlStateNormal];
            self.imageView.contentMode = UIViewContentModeCenter;
            
            // 3.设置button右边的切割线
            UIImage *img = [UIImage imageNamed:@"separator_topbar_item.png"];
            UIImageView *divider = [[UIImageView alloc] initWithImage:img];
            divider.bounds = CGRectMake(0, 0, 2, kTopMenuItemH * 0.7);
            divider.center = CGPointMake(kTopMenuItemW, kTopMenuItemH * 0.5);
            [self addSubview:divider];
            
            // 4.设置button选中时的背景
            [self setBackgroundImage:[UIImage imageStretchedWithName:@"slider_filter_bg_normal.png"] forState:UIControlStateSelected];
        }
        return self;
    }
    
    - (void)setTitle:(NSString *)title
    {
        _title = title;
        
        [self setTitle:title forState:UIControlStateNormal];
    }
    // 自己固定顶部菜单项button的好宽高
    - (void)setFrame:(CGRect)frame
    {
        frame.size = CGSizeMake(kTopMenuItemW, kTopMenuItemH);
        [super setFrame:frame];
    }
    // 左文字的frame
    - (CGRect)titleRectForContentRect:(CGRect)contentRect
    {
        CGFloat h = contentRect.size.height;
        CGFloat w = contentRect.size.width * kTitleScale;
        return CGRectMake(0, 0, w, h);
    }
    // 右图片的frame
    - (CGRect)imageRectForContentRect:(CGRect)contentRect
    {
        CGFloat h = contentRect.size.height;
        CGFloat x = contentRect.size.width * kTitleScale;
        CGFloat w = contentRect.size.width - x;
        return CGRectMake(x, 0, w, h);
    }
    
    
    
    @end
    



    PopMenu.h

    //
    //  PopMenu.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  PopMenu是点击顶部button项,在其下方弹出的菜单的父类,成员有:以下是一个cover蒙板,上面是一个contentView(包括着scrollView和subTitleImgView,当中scrollView里面放的全是PopMenuItem,如美食,如海淀区.....subTitleImgView里面放的全是美食以下的全部子标题,如川菜 湘菜 粤菜)
    
    
    
    //  点击dock上面的【团购】button,创建一个经过导航包装的DealList控制器,控制器的上面是导航栏,导航栏右边是searchBar,导航栏左边是一个大button(TopMenu)(内部由三个小button组成<TopMenuItem>),点击TopMenu中的某一个button<TopMenuItem>,会在其下方,弹出一个PopMenu,PopMenu包括二个部分,见上面
    
    #import <UIKit/UIKit.h>
    #import "SubTitleImgViewDelegate.h"
    @class SubTitleImgView, PopMenuItem;
    
    @interface PopMenu : UIView <SubTitleImgViewDelegate>
    {
        // 以下成员是开放给子类訪问和改动的
        
        // 容纳全部的分类或商区,如美食,如海淀区
        UIScrollView *_scrollView;
        
        // 容纳全部子标题的ImgView,里面全是一个个button,如美食以下的川菜、湘菜、粤菜等
        SubTitleImgView *_subTitleImgView;
        
        // item的父类,弹出菜单项:记录当前选中的菜单项,如美食,如海淀区(此是父类)
        PopMenuItem *_selectedPopMenuItem;
    }
    
    // 弹出菜单隐藏完成之后,要通知顶部菜单
    @property (nonatomic, copy) void (^hideBlock)();
    
    // 供外部调用,通过动画显示 PopMenu
    - (void)showPopMenu;
    // 供外部调用,通过动画隐藏 PopMenu
    - (void)hidePopMenu;
    
    
    @end
    

    PopMenu.m


    创建并加入一个cover,一个ContentView,并向ContentView加入一个ScrollView


    //
    //  PopMenu.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  PopMenu是点击顶部button项,在其下方弹出的菜单的父类,成员有:以下是一个cover蒙板,上面是一个contentView(包含着scrollView和subTitleImgView,当中scrollView里面放的全是PopMenuItem,如美食,如海淀区.....subTitleImgView里面放的全是美食以下的全部子标题,如川菜 湘菜 粤菜)
    
    
    
    //  点击dock上面的【团购】button,创建一个经过导航包装的DealList控制器,控制器的上面是导航栏,导航栏右边是searchBar,导航栏左边是一个大button(TopMenu)(内部由三个小button组成<TopMenuItem>),点击TopMenu中的某一个button<TopMenuItem>,会在其下方,弹出一个PopMenu,PopMenu包含二个部分,见上面
    
    #import "PopMenu.h"
    // 遮罩
    #import "Cover.h"
    
    
    // subTitleImgView里面放的全是美食以下的全部子标题,如川菜湘菜粤菜
    #import "SubTitleImgView.h"
    // scrollView里面放的全是PopMenuItem,如美食,如海淀区
    #import "PopMenuItem.h"
    #import "MetaDataTool.h"
    
    
    
    
    #import "CategoryPopMenuItem.h"
    #import "DistrictPopMenuItem.h"
    #import "OrderPopMenuItem.h"
    
    
    
    
    @interface PopMenu()
    {
        // 上面是_contentView,包含scrollView和subTitleImgView,当中scrollView里面放的全是PopMenuItem,如美食,如海淀区.....subTitleImgView里面放的全是美食以下的全部子标题,如川菜湘菜粤菜
        UIView *_contentView;
        // 遮罩
        Cover *_cover;
        
    }
    @end
    
    @implementation PopMenu
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 0.为适应横竖屏的变化,设置self PopMenu宽高自己主动伸缩
            self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
            
            // 1.加入蒙板(遮盖),而且点击蒙板后,隐藏并移除popMenu的contentView(内部是scrollView和subTitleImgView),并置cover透明
            [self addCover];
            
            // 2.加入内容view(内部是scrollView和subTitleImgView)
            [self addContentView];
            
            // 3.加入ScrollView到contentView
            [self addScrollView];
            
        }
        return self;
    }
    
    
    // 1.加入蒙板(遮盖),而且点击蒙板后,隐藏并移除popMenu的contentView(内部是scrollView和subTitleImgView),并置cover透明
    - (void)addCover
    {
        _cover = [Cover coverWithTarget:self action:@selector(hideContentView)];
        _cover.frame = self.bounds;
        [self addSubview:_cover];
    }
    
    // 2.加入内容view(内部是scrollView和subTitleImgView)
    - (void)addContentView
    {
        
        _contentView = [[UIView alloc] init];
        // 默认高度是一个popMenuItem高度
        _contentView.frame = CGRectMake(0, 0, self.frame.size.width, kBottomMenuItemH);
        // 宽度伸缩,可是高度其内部通过数据源的多少自己主动计算行数及总高度
        _contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        [self addSubview:_contentView];
    }
    
    // 3.加入ScrollView到contentView
    -(void)addScrollView
    {
        _scrollView = [[UIScrollView alloc] init];
        _scrollView.showsHorizontalScrollIndicator = NO;
        // 宽高伸缩,高度固定死为一个popMenuItem高度
        _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        _scrollView.frame = CGRectMake(0, 0, self.frame.size.width, kBottomMenuItemH);
        _scrollView.backgroundColor = [UIColor whiteColor];
        [_contentView addSubview:_scrollView];
    }
    
    #pragma mark - 父类接口方法
    // 本父类方法的作用:控制popMenuItem的状态切换,假设popMenuItem有子标题(如美食),显示子标题showSubTitleImgView,假设没有子标题(如电影),就可隐藏掉弹出button了
    - (void)popMenuItemClicked:(PopMenuItem *)item
    {
        // 父类提供的一个接口方法,当它子类中的MenuItem addTarget为 popMenuItemClicked时,假设子类 没有实现popMenuItemClicked方法,就会到父类这儿来找popMenuItemClicked方法,
        // 因此,本方法的目的是:监听全部它的子类(如CategoryPopMenu,DistrictPopMenu)的菜单项的点击
        
        
        // 1.控制item的状态切换
        _selectedPopMenuItem.selected = NO;
        item.selected = YES;
        _selectedPopMenuItem = item;
        
        // 2.查看是菜单项,如美食,如海淀区  否有子分类,假设有子分类才要显示SubTitleImgView,并为其提供数据源,子标题文字组成的数组
        if (item.subTitlesArr.count) {
            // 有子标题,才要动画显示全部的子标题
            [self showSubTitleImgView:item];
        } else { // 由于没有子标题,所以隐藏全部的子标题,而且就能够直接设置当前Category或District或Order为刚才点击的PopMenuItem
            [self hideSubTitleImgView:item];
        }
    }
    
    // 假设被点击的popMenuItem有子标题,才要创建而且动画显示SubTitleImgView,并为其提供数据源,即子标题文字组成的数组
    - (void)showSubTitleImgView:(PopMenuItem *)item
    {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:kDefaultAnimDuration];
        // 全部的PopMenu子类(如CategoryPopMenu和DistrictPopMenu和OrderPopMenu)共用一个_subTitleImgView,展示子分类的全部子标题
        if (_subTitleImgView == nil) {
            _subTitleImgView = [[SubTitleImgView alloc] init];
            // 设置self PopMenu为_subTitleImgView的代理目的是:两个,当点击_subTitleImgView里面的button时,获知button的标题,另外一个就是告诉_subTitleImgView当前选中的PopMenu是哪一个类别,是美食?还是海淀区???
            // 而且代理方法,由对应的子类(如CategoryPopMenu和DistrictPopMenu和OrderPopMenu)去实现
            _subTitleImgView.delegate = self;
        }
        
        // 设置子标题的frame,y位于scrollView的下方,高度?

    ???

    ? _subTitleImgView.frame = CGRectMake(0, kBottomMenuItemH, self.frame.size.width, _subTitleImgView.frame.size.height); // 设置子标题的主标题 ??

    ?? _subTitleImgView.mainTitle = [item titleForState:UIControlStateNormal]; // 设置子标题须要显示的内容(带去要显示的数据源,即全部的子标题组成的数组) // 重要~~~供子类 去实现的,内部会拦截此方法,加入全部的子标题button,并设置文字 _subTitleImgView.titleArr = item.subTitlesArr; // 当前子标题没有正在展示的时候,就须要运行动画显示 _subTitleImgView if (_subTitleImgView.superview == nil) { [_subTitleImgView showSubTitleImgViewWithAnimation]; } // 加入子标题到内容view-scrollView底部 [_contentView insertSubview:_subTitleImgView belowSubview:_scrollView]; // 重要~依据_subTitleImgView不同的高度,调整整个contentView的高度~~~ CGRect cf = _contentView.frame; cf.size.height = CGRectGetMaxY(_subTitleImgView.frame); _contentView.frame = cf; [UIView commitAnimations]; } // 由于假设被点击的popMenuItem没有子标题,所以隐藏全部的子标题,而且就能够直接设置当前Category或District或Order为刚才点击的PopMenuItem - (void)hideSubTitleImgView:(PopMenuItem *)item { // 1.通过动画隐藏子标题 if (_subTitleImgView) { [_subTitleImgView hideSubTitleImgViewWithAnimation]; } // 2.移除后,必须又一次调整contentView的高度为默认的一个PopMenuItem的高度 CGRect cf = _contentView.frame; cf.size.height = kBottomMenuItemH; _contentView.frame = cf; // 3.由于没有子标题,所以就能够直接设置工具类中的当前Category或District或Order为刚才点击的PopMenuItem,工具类内部会拦截,并发出通知,通知给TopMenu等 NSString *title = [item titleForState:UIControlStateNormal]; if ([item isKindOfClass:[CategoryPopMenuItem class]]) { // 假设点击的PopMenuItem是 分类PopMenuItem [MetaDataTool sharedMetaDataTool].currentCategoryName = title; } else if ([item isKindOfClass:[DistrictPopMenuItem class]]) { // 假设点击的PopMenuItem是 商区PopMenuItem [MetaDataTool sharedMetaDataTool].currentDistrictName = title; } else { // 假设点击的PopMenuItem是 排序PopMenuItem [MetaDataTool sharedMetaDataTool].currentOrder = [[MetaDataTool sharedMetaDataTool] orderWithName:title]; } } #pragma mark 显示ContentView,供外部调用,如点击了TopMenu时调用,且当前没有PopMenu正在显示 - (void)showPopMenu { _contentView.transform = CGAffineTransformMakeTranslation(0, -_contentView.frame.size.height); _contentView.alpha = 0; _cover.alpha = 0; [UIView animateWithDuration:kDefaultAnimDuration animations:^{ // 1.scrollView从上面 -> 以下 _contentView.transform = CGAffineTransformIdentity; _contentView.alpha = 1; // 2.遮盖(0 -> 0.4) [_cover alphaReset]; }]; } #pragma mark 隐藏ContentView,供外部调用,如点击了Cover或同一个TopMenuItem时调用,且当前没有PopMenu正在显示 // 如点击遮盖时,隐藏并移除popMenu的contentView(内部是scrollView和subTitleImgView),并置cover透明 - (void)hidePopMenu { // 假设隐藏完成弹出菜单的 _contentView之后,要通知调用者(顶部菜单)更改顶部菜单项文字 if (_hideBlock) { _hideBlock(); } [UIView animateWithDuration:kDefaultAnimDuration animations:^{ // _contentView向上消失,即移动一个自身的高度 _contentView.transform = CGAffineTransformMakeTranslation(0, -_contentView.frame.size.height); _contentView.alpha = 0; // 2.遮盖(0.4 -> 0) _cover.alpha = 0; } completion:^(BOOL finished) { // _contentView全然看不见了之后,就将弹出菜单从父控件中移除 [self removeFromSuperview]; // 而且恢复_contentView的属性 _contentView.transform = CGAffineTransformIdentity; _contentView.alpha = 1; [_cover alphaReset]; }]; } @end


    PopMenuItem.h

    //
    //  PopMenuItem.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  底部弹出菜单的菜单项 (是一个父类)  抽取的特征:1,右边有分隔线,2.宽高全统一,3.选中时,背景图片统一,4文字颜色
    
    #import <UIKit/UIKit.h>
    
    @interface PopMenuItem : UIButton
    
    
    // 本接口,专门交给子类实现
    // 数据源,子标题数组,全部子标题的名字组成的数组,
    // 比方 美食 以下有多少个category
    // 比方 海淀区 以下有多少个place
    - (NSArray *)subTitlesArr;
    @end
    PopMenuItem.m

    //
    //  PopMenuItem.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  底部弹出菜单的菜单项 (是一个父类)  抽取的特征:1,右边有分隔线,2.宽高全统一,3.选中时,背景图片统一,4文字颜色
    
    #import "PopMenuItem.h"
    
    @implementation PopMenuItem
    
    
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 1.右边的切割线
            UIImage *img = [UIImage imageNamed:@"separator_filter_item.png"];
            UIImageView *divider = [[UIImageView alloc] initWithImage:img];
            divider.bounds = CGRectMake(0, 0, 2, kBottomMenuItemH * 0.7);
            divider.center = CGPointMake(kBottomMenuItemW, kBottomMenuItemH * 0.5);
            [self addSubview:divider];
            
            // 2.文字颜色
            [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            self.titleLabel.font = [UIFont systemFontOfSize:16];
            
            // 3.设置被选中时的背景
            [self setBackgroundImage:[UIImage imageStretchedWithName:@"bg_filter_toggle_hl.png"] forState:UIControlStateSelected];
        }
        return self;
    }
    
    // 菜单项的宽高固定为一个button的宽和高
    - (void)setFrame:(CGRect)frame
    {
        frame.size = CGSizeMake(kBottomMenuItemW, kBottomMenuItemH);
        [super setFrame:frame];
    }
    
    // 取消高亮显示状态
    - (void)setHighlighted:(BOOL)highlighted {}
    
    // 本接口,专门交给子类实现
    // 数据源,子标题数组,全部子标题的名字组成的数组
    // 比方 美食 以下有多少个category
    // 比方 海淀区 以下有多少个place
    - (NSArray *)subTitlesArr
    {
        return nil;
    }
    
    @end
    
    Cover.h

    //
    //  Cover.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  PopMenu是点击顶部button项(TopMenuItem),在其下方弹出的菜单(XXXPopMenu)的父类,成员有:以下是一个cover蒙板,上面是一个contentView(包括着scrollView和subTitleImgView,当中scrollView里面放的全是PopMenuItem,如美食,如海淀区.....subTitleImgView里面放的全是美食以下的全部子标题,如川菜湘菜粤菜)
    
    #import <UIKit/UIKit.h>
    
    @interface Cover : UIView
    
    + (id)cover;
    // 绑定tap手势
    + (id)coverWithTarget:(id)target action:(SEL)action;
    
    - (void)alphaReset;
    @end
    


    Cover.m

    //
    //  Cover.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  PopMenu是点击顶部button项(TopMenuItem),在其下方弹出的菜单(XXXPopMenu)的父类,成员有:以下是一个cover蒙板,上面是一个contentView(包括着scrollView和subTitleImgView,当中scrollView里面放的全是PopMenuItem,如美食,如海淀区.....subTitleImgView里面放的全是美食以下的全部子标题,如川菜湘菜粤菜)
    
    #import "Cover.h"
    
    
    // 1为全黑
    #define kAlpha 0.7
    @implementation Cover
    
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 1.背景色
            self.backgroundColor = [UIColor blackColor];
            
            // 2.它是蒙在tableView上面,所以要同tableView一样,宽高自己主动伸缩
            self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
            
            // 3.透明度
            self.alpha = kAlpha;
        }
        return self;
    }
    
    - (void)alphaReset
    {
        self.alpha = kAlpha;
    }
    
    + (id)cover
    {
        return [[self alloc] init];
    }
    
    + (id)coverWithTarget:(id)target action:(SEL)action
    {
        Cover *cover = [self cover];
        // 绑定一个,tap手势监听器
        [cover addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:target action:action]];
        return cover;
    }
    
    
    @end
    


    SubTitleImgView.h

    容纳全部子标题的ImgView,里面全是一个个button,

    如美食以下的川菜、湘菜、粤菜等...

    如海淀区以下的中关村、五棵松、香山等...

    而且全部的弹出菜单PopMenu都共用此一个SubTitleImgView

    //
    //  SubTitleImgView.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    // 容纳全部子标题的ImgView,里面全是一个个button,如美食以下的川菜、湘菜、粤菜等...如海淀区以下的中关村、五棵松、香山等,注意全部的弹出菜单PopMenu共用此一个SubTitleImgView
    
    #import <UIKit/UIKit.h>
    
    @protocol SubTitleImgViewDelegate;
    
    
    @interface SubTitleImgView : UIImageView
    
    // 数据源,主标题,每个子标题数组都有,且是在第一个位置---> 【全部】
    @property (nonatomic, copy) NSString *mainTitle;
    
    // 数据源,须要显示的全部的子标题button的文字组成的数组,外部传入,如美食以下的川菜、湘菜、粤菜等...如海淀区以下的中关村、五棵松、香山等
    @property (nonatomic, strong) NSMutableArray *subTitlesArr;
    
    @property (nonatomic, weak) id<SubTitleImgViewDelegate> delegate;
    // 代理和block的效果等价
    //@property (nonatomic, copy) void (^setBtnTitleBlock)(NSString *title);
    //@property (nonatomic, copy) NSString *(^getBtnTitleBlock)();
    
    // 通过动画显示出来SubTitleImgView,供创建者调用
    - (void)showSubTitleImgViewWithAnimation;
    // 通过动画隐藏SubTitleImgView,供创建者调用
    - (void)hideSubTitleImgViewWithAnimation;
    @end
    

    SubTitleImgView.h

    容纳全部子标题的ImgView,里面全是一个个button,

    如美食以下的川菜、湘菜、粤菜等...

    如海淀区以下的中关村、五棵松、香山等...

    而且全部的弹出菜单PopMenu都共用此一个SubTitleImgView


    //
    //  SubTitleImgView.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    // 容纳全部子标题的ImgView,里面全是一个个button,如美食以下的川菜、湘菜、粤菜等...如海淀区以下的中关村、五棵松、香山等,注意全部的弹出菜单PopMenu共用此一个SubTitleImgView
    
    #import "SubTitleImgView.h"
    #import "MetaDataTool.h"
    #import "SubTitleImgViewDelegate.h"
    
    #define kSubTitleBtnW 100
    #define kSubTitleBtnH 40
    
    // 里面用到的全部button,因样式统一,所以抽取一个基类
    @interface SubTitleBtn : UIButton
    @end
    
    @implementation SubTitleBtn
    - (void)drawRect:(CGRect)rect
    {
        // 设置选中状态下,SubTitleBtn的frame和背景
        if (self.selected) {
            CGRect frame = self.titleLabel.frame;
            frame.origin.x -= 5;
            frame.size.width += 10;
            frame.origin.y -= 5;
            frame.size.height += 10;
            [[UIImage imageStretchedWithName:@"slider_filter_bg_active.png"] drawInRect:frame];
        }
    }
    @end
    
    @interface SubTitleImgView()
    {
        // 记住当前选中的SubTitleBtn
        UIButton *_selectedSubTitleBtn;
    }
    @end
    
    @implementation SubTitleImgView
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // SubTitleImgView的宽度自由伸缩
            self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
            // SubTitleImgView的背景图片
            self.image = [UIImage imageStretchedWithName:@"bg_subfilter_other.png"];
            
            // 重要~~~~裁剪掉超出父控件范围内的子控件(超出父控件范围内的子控件不显示)
            self.clipsToBounds = YES;
            // 让imageView里面的一个个button能够点击,如美食(PopMenuItem)以下的川菜、湘菜、粤菜等
            self.userInteractionEnabled = YES;
        }
        return self;
    }
    #pragma mark - 拦截setter数据源数组方法,创建全部相应个数的button
    // 数据源,需要显示的全部的子标题button的文字组成的数组,外部传入,拦截setter方法
    - (void)setTitleArr:(NSArray *)titleArr
    {
        // 1.用成员变量,记住全部的子标题,如美食(PopMenuItem)以下的川菜、湘菜、粤菜等
        // 全部子标题中,排在首位的都是:固定字符串--->【全部】
        [_subTitlesArr addObject:kAll];
        // 将其它子标题加到后面,如美食(PopMenuItem)以下的川菜、湘菜、粤菜等
        [_subTitlesArr addObjectsFromArray:titleArr];
        
        
        // 2.遍历子标题数组,懒载入创建可重用的子标题button
        [self addAllSubTitlesBtn];
        
        
        // 3.每当setter数据源改变之后,button的位置和个数都要又一次排布,所以手动调用一次 layoutSubviews方法
        [self layoutSubviews];
        
        /*
         layoutSubviews在以下情况下会被调用:
         1、init初始化不会触发layoutSubviews
         2、addSubview会触发layoutSubviews
         3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
         4、滚动一个UIScrollView会触发layoutSubviews
         5、旋转Screen会触发父UIView上的layoutSubviews事件
         6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
         */
    }
    
    
    // 2.遍历子标题数组,懒载入创建可重用的子标题button
    - (void)addAllSubTitlesBtn
    {
        
        int count = _subTitlesArr.count;
        // 遍历子标题数组,懒载入创建button,并设置button的文字
        for (int i = 0; i<count; i++) {
            // 1.重要~~~如i位置没有button与之相应,则创建一个新的button,显示i位置的子标题文字
            UIButton *btn = nil;
            // self是SubTitleImgView,里面的子控件全是一个个代表子标题的button
            // button个数不够,创建SubTitleBtn,而且绑定监听事件
            if (i >= self.subviews.count) {
                // 创建一个新的子标题button
                btn = [SubTitleBtn buttonWithType:UIButtonTypeCustom];
                // 绑定监听事件
                [btn addTarget:self action:@selector(subTitleBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
                // 设置文字颜色
                [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
                // 设置文字字体
                btn.titleLabel.font = [UIFont systemFontOfSize:13];
                // 加入到SubTitleImgView
                [self addSubview:btn];
            } else {
                // 假设子控件数组中有足量的button,就直接取出来,重用
                btn = self.subviews[i];
            }
            
            // 2.设置button独一无二的文字(并将button显示)
            [btn setTitle:_subTitlesArr[i] forState:UIControlStateNormal];
            btn.hidden = NO;
            
            // 3.推断该button要不要默认选中,依据是:该button文字是不是和当前选中的分类或商区名字一样,代理会负责告诉我subTitleImgView 当前的分类名或者商区名字
            if ([_delegate respondsToSelector:@selector(subTitleImgViewGetCurrentBtnTitle:)]) {
                // 代理会负责告诉我subTitleImgView 当前的分类名或者商区名字
                NSString *currentBtnTitle = [_delegate subTitleImgViewGetCurrentBtnTitle:self];
                
                // 选中了主标题,选中第0个button(“全部”)
                if ([currentBtnTitle isEqualToString:_mainTitle] && i == 0) {
                    btn.selected = YES;
                    _selectedSubTitleBtn = btn;
                } else {
                    btn.selected = [_subTitlesArr[i] isEqualToString:currentBtnTitle];
                    // 重要细节 ~~~~假设在不同的类别或商区,发现了同名的,则也视为选中了
                    if (btn.selected) {
                        _selectedSubTitleBtn = btn;
                    }
                }
            } else {
                btn.selected = NO;
            }
        }
        
        
        // 3.重要~~~隐藏子控件数组中多余的button,如子标题文字数组有8项,而子控件数组有10个,那么多余的两个button就要隐藏起来
        for (int i = count; i<self.subviews.count; i++) {
            UIButton *btn = self.subviews[i];
            btn.hidden = YES;
        }
    }
    // 监听小标题(button)点击,如美食(PopMenuItem)以下的川菜、湘菜、粤菜等
    - (void)subTitleBtnClicked:(UIButton *)btn
    {
        // 1.三步曲,控制button状态切换
        _selectedSubTitleBtn.selected = NO;
        btn.selected = YES;
        _selectedSubTitleBtn = btn;
        
        // 2.告诉代理,我点击选中了谁
        if ([_delegate respondsToSelector:@selector(subTitleImgView:btnClicked:)]) {
            
            // 取出当前被点的button的文字
            NSString *title = [btn titleForState:UIControlStateNormal];
            // 假设 是 【全部】
            if ([title isEqualToString:kAll]) { // 全部 --> 大标题
                title = _mainTitle;
            }
            // 告诉代理(调用者),当前被点击的button的文字...
            [_delegate subTitleImgView:self btnClicked:title];
        }
    }
    
    #pragma mark - 覆盖UIView的方法,又一次布局SubTitleImgView全部子控件的位置
    // 控件SubTitleImgView本身的宽高发生改变等情况下就会自己主动触发layoutSubviews方法
    - (void)layoutSubviews
    {
        // 1.一定要调用super
        [super layoutSubviews];
        
        // 2.依据屏幕宽,算出总的列数,并对全部子标题button设置九宫格frame
        int columns = self.frame.size.width / kSubTitleBtnW;
        // 依据数据源的个数,遍历相应数目的button,依据i设置其frame
        for (int i = 0; i<_subTitlesArr.count; i++) {
            
            UIButton *btn = self.subviews[i];
            // 设置位置
            // 所在的列
            CGFloat x = i % columns * kSubTitleBtnW;
            // 所在的行
            CGFloat y = i / columns * kSubTitleBtnH;
            // 设置独一无二的frame
            btn.frame = CGRectMake(x, y, kSubTitleBtnW, kSubTitleBtnH);
        }
        
        
        // 3.重要~~~计算出子标题的行数以后,必需要设置SubTitleImgView的总高度,三步曲
        // 小算法,求出总的行数,以确定SubTitleImgView的总高度
        int rows = (_subTitlesArr.count + columns - 1) / columns;
        CGRect frame = self.frame;
        frame.size.height = rows * kSubTitleBtnH;
        self.frame = frame;
    }
    
    
    
    
    
    
    #pragma mark - 显示和隐藏子标题ImgView,供创建者调用
    // 动画显示self  (SubTitleImgView),供创建者调用
    - (void)showSubTitleImgViewWithAnimation
    {
        // 1.重要~~~必需要先调用layoutSubviews,先算出在当前数据源titleArr数组个数的情况下,self的总高度~~~~
        [self layoutSubviews];
        
        
        // 2.先设置y为负的self的总高度(方法ayoutSubviewsy已经计算过了)
        self.transform = CGAffineTransformMakeTranslation(0, -self.frame.size.height);
        // 先设置为透明
        self.alpha = 0;
        
        // 3.动画显示出来
        [UIView animateWithDuration:kDefaultAnimDuration animations:^{
            self.transform = CGAffineTransformIdentity;
            self.alpha = 1;
        }];
    }
    // 动画隐藏self  (SubTitleImgView),供创建者调用
    - (void)hideSubTitleImgViewWithAnimation
    {
        // 动画设置y为负的self的总高度(慢慢向上消失效果)
        [UIView animateWithDuration:kDefaultAnimDuration animations:^{
            self.transform = CGAffineTransformMakeTranslation(0, -self.frame.size.height);
            self.alpha = 0;
        } completion:^(BOOL finished) {
            // 重要~~~~动画完毕后,将其从父控件中移除,而且将self的高度置0,目的是方便下次动画出现的时候,能够从0開始向下展开
            [self removeFromSuperview];
            
            CGRect f = self.frame;
            f.size.height = 0;
            self.frame = f;
            // ?

    ??

    会不会与上面这一句功能反复 self.transform = CGAffineTransformIdentity; self.alpha = 1; }]; } @end



    SubTitleImgView定义的协议

    SubTitleImgViewDelegate.h

    //
    //  SubTitleViewDelegate.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  分类或商区的子标题的代理方法,当点击了【分类或商区的子标题button】时,通知代理
    
    #import <Foundation/Foundation.h>
    
    @class SubTitleImgView;
    @protocol SubTitleImgViewDelegate <NSObject>
    
    @optional
    
    
    // 当SubTitleImgView里面的button被点击了的时候调用,告诉其它全部想知道的类(即SubTitleImgView的代理):被点击的button的文字【被点击的分类或商区的子标题button上的文字】
    - (void)subTitleImgView:(SubTitleImgView *)subTitleImgView btnClicked:(NSString *)btnTitle;
    
    
    
    
    // 返回当前选中的文字(比方分类菜单。就返回当前选中的分类名称。区域菜单。就返回当前选中的区域名称),目的是子标题button出现前,将选中的那个高亮(回显)~~~
    // 得到当前选中的分类或商区button上的文字,用于与新出现的button文字进行推断,假设同样,则在SubTitleImgView出现之前,将SubTitleImgView上面的该button置为高亮,其它全为普通
    // 假设SubTileImgView的代理是CategoryPopMenu,说明应该从工具类返回currentCategoryName给SubTileImgView
    - (NSString *)subTitleImgViewGetCurrentBtnTitle:(SubTitleImgView *)subTitleImgView;
    @end
    


    View的层级关系示意图:

    父类:PopMenu

    其子类:CategoryPopMenu、DistrictPopMenu、OrderPopMenu


    父类:PopMenuItem

    其子类:CategoryPopMenuItem、DistrictPopMenuItem、OrderPopMenuItem




    子类:CategoryPopMenu

    //
    //  CategoryPopMenu.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击顶部菜单中的分类频道 button(顶部菜单项),弹出的菜单,继承自PopMenu,包含二个部分(上:contentView,包含scrollView和SubTitleImgView,下:蒙板)
    
    #import "PopMenu.h"
    
    @interface CategoryPopMenu : PopMenu
    
    @end
    //
    //  CategoryPopMenu.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击顶部菜单中的分类频道 button(顶部菜单项),弹出的菜单,继承自PopMenu,包含二个部分(上:contentView,包含scrollView和SubTitleImgView,下:蒙板)
    
    #import "CategoryPopMenu.h"
    // 分类菜单项如:美食
    #import "CategoryPopMenuItem.h"
    #import "MetaDataTool.h"
    
    @implementation CategoryPopMenu
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 1.往scrollView里面加入内容(CategoryPopMenuItem)
            [self addCategoryPopMenuItem];
        }
        return self;
    }
    // 1.往scrollView里面加入内容(CategoryPopMenuItem)
    - (void)addCategoryPopMenuItem
    {
        // 获取数据源,工具类提供allCategoriesArr对象数组
        NSArray *categories = [MetaDataTool sharedMetaDataTool].allCategoriesArr;
        
        // 1.往scrollView里面加入内容(CategoryPopMenuItem)
        int count = categories.count;
        for (int i = 0; i<count; i++) {
            // 创建并逐一加入CategoryPopMenuItem, 分类菜单项如:美食
            CategoryPopMenuItem *item = [[CategoryPopMenuItem alloc] init];
            // 设置CategoryPopMenuItem要显示的数据源
            item.category = categories[i];
            // 当点击美食时,会到父类中去找方法popMenuItemClicked
            [item addTarget:self action:@selector(popMenuItemClicked:) forControlEvents:UIControlEventTouchUpInside];
            // 由于是在scrollView里面,所以所有水平排列
            item.frame = CGRectMake(i * kBottomMenuItemW, 0, 0, 0);
            // 加到scrollView
            [_scrollView addSubview:item];
            
            // 默认选中第0个item
            if (i == 0) {
                item.selected = YES;
                _selectedPopMenuItem = item;
            }
        }
        // 2.依据CategoryPopMenuItem的多少,设置_scrollView滚动范围
        _scrollView.contentSize = CGSizeMake(count * kBottomMenuItemW, 0);
    }
    
    #pragma mark - SubTitleImgViewDelegate代理方法
    // 当SubTitleImgView里面的子标题button点击时,会调用此方法,目的是 传递点击的【分类或商区的子标题button】文字
    - (void)subTitleImgView:(SubTitleImgView *)subTitleImgView btnClicked:(NSString *)btnTitle
    {
        [MetaDataTool sharedMetaDataTool].currentCategoryName = btnTitle;
    }
    // 难点??? 得到并推断当前button是否选中的文字(比方分类菜单,就返回当前选中的分类名称;区域菜单,就返回当前选中的区域名称)
    - (NSString *)subTitleImgViewGetCurrentBtnTitle:(SubTitleImgView *)subTitleImgView
    {
        // 假设SubTileImgView的代理是CategoryPopMenu,说明应该从工具类返回currentCategoryName给SubTileImgView
        return [MetaDataTool sharedMetaDataTool].currentCategoryName;
    }
    @end




    子类:CategoryPopMenuItem

    //
    //  CategoryPopMenuItem.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  在CategoryPopMenu的第一层(即scrollView)里面的一个button,如美食,button图片在上面,文字在以下,且button右边是一根竖线
    
    #import "PopMenuItem.h"
    @class MyCategory;
    @interface CategoryPopMenuItem : PopMenuItem
    
    // 数据源,本button,须要显示的分类对象模型,一个PopMenuItem 相应一个分类,如美食
    @property (nonatomic, strong) MyCategory *category;
    @end
    

    //
    //  CategoryPopMenuItem.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  在CategoryPopMenu的第一层(即scrollView)里面的一个button,button图片在上面,文字在以下,且button右边是一根竖线
    
    #import "CategoryPopMenuItem.h"
    #import "MyCategory.h"
    
    // 图片在上,文字在下
    #define kTitleHeightRatio 0.3
    @implementation CategoryPopMenuItem
    
    
    
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 1.文字居中对齐
            self.titleLabel.textAlignment = NSTextAlignmentCenter;
            
            // 2.图片中心缩放
            self.imageView.contentMode = UIViewContentModeCenter;
        }
        return self;
    }
    
    
    // 父类的方法,供子类实现
    // 数据源,子标题数组,全部子标题的名字组成的数组,  本接口,专门交给子类实现
    // 比方 美食 以下有多少个subCategory
    // 比方 海淀区 以下有多少个place
    - (NSArray *)subTitlesArr
    {
        return _category.subcategories;
    }
    
    // 拦截数据源的setter方法,设置button的图片和文字
    - (void)setCategory:(MyCategory *)category
    {
        _category = category;
        
        // 1.图标
        [self setImage:[UIImage imageNamed:category.icon] forState:UIControlStateNormal];
        
        // 2.标题
        [self setTitle:category.name forState:UIControlStateNormal];
    }
    
    
    #pragma mark 设置button上面的图片的frame
    - (CGRect)imageRectForContentRect:(CGRect)contentRect {
        return CGRectMake(0, 0, contentRect.size.width, contentRect.size.height * (1 - kTitleHeightRatio));
    }
    
    #pragma mark 设置button以下的标题的frame
    - (CGRect)titleRectForContentRect:(CGRect)contentRect {
        CGFloat titleHeight = contentRect.size.height * kTitleHeightRatio;
        CGFloat titleY = contentRect.size.height - titleHeight;
        return CGRectMake(0, titleY, contentRect.size.width,  titleHeight);
    }
    
    
    @end
    

    子类:DistrictPopMenu

    //
    //  DistrictPopMenu.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击顶部菜单中的 所有商区 button(顶部菜单项),弹出的菜单,继承自PopMenu,包含二个部分(上:contentView,包含scrollView和SubTitleImgView,下:蒙板)
    
    #import "PopMenu.h"
    
    @interface DistrictPopMenu : PopMenu
    
    @end
    
    //
    //  DistrictPopMenu.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-15.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击顶部菜单中的 所有商区 button(顶部菜单项),弹出的菜单,继承自PopMenu,包含二个部分(上:contentView,包含scrollView和SubTitleImgView,下:蒙板)
    
    #import "DistrictPopMenu.h"
    #import "DistrictPopMenuItem.h"
    #import "MetaDataTool.h"
    #import "District.h"
    // 商区依赖城市
    #import "City.h"
    
    #import "SubTitleImgView.h"
    
    @interface DistrictPopMenu ()
    {
        NSMutableArray *_menuItems;
    }
    
    @end
    @implementation DistrictPopMenu
    
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            _menuItems = [NSMutableArray array];
            
            [self cityChange];
            
            // 监听城市改变
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cityChange) name:kCityChangeNote object:nil];
        }
        return self;
    }
    
    - (void)cityChange
    {
        // 1.获取当前选中的城市对象,保存在工具中
        City *city = [MetaDataTool sharedMetaDataTool].currentCity;
        
        // 2.当前城市的所有区域,包含所有商区+下属商区数组(城市相应的成员)
        NSMutableArray *districts = [NSMutableArray array];
        // 2.1.所有商区
        District *all = [[District alloc] init];
        all.name = kAllDistrict;
        [districts addObject:all];
        // 2.2.其它商区,下属商区数组(城市相应的成员)
        [districts addObjectsFromArray:city.districts];
        
        // 3.遍历所有的商区对象,创建并设置button标题
        int count = districts.count;
        for (int i = 0; i<count; i++) {
            DistrictPopMenuItem *item = nil;
            if (i >= _menuItems.count) { // 不够
                item = [[DistrictPopMenuItem alloc] init];
                [item addTarget:self action:@selector(popMenuItemClicked:) forControlEvents:UIControlEventTouchUpInside];
                [_menuItems addObject:item];
                [_scrollView addSubview:item];
            } else {
                item = _menuItems[i];
            }
            
            item.hidden = NO;
            item.district = districts[i];
            item.frame = CGRectMake(i * kBottomMenuItemW, 0, 0, 0);
            
            // 默认选中第0个item
            if (i == 0) {
                item.selected = YES;
                _selectedPopMenuItem = item;
            } else {
                item.selected = NO;
            }
        }
        
        // 4.隐藏多余的item
        for (int i = count; i<_menuItems.count; i++) {
            DistrictPopMenuItem *item = _scrollView.subviews[i];
            item.hidden = YES;
        }
        
        // 5.设置scrollView的内容尺寸
        _scrollView.contentSize = CGSizeMake(count * kBottomMenuItemW, 0);
        
        // 6.隐藏子标题(在父类定义的)
        [_subTitleImgView hideSubTitleImgViewWithAnimation];
    }
    
    
    
    #pragma mark - SubTitleImgViewDelegate代理方法
    // 当SubTitleImgView里面的子标题button点击时,会调用此方法,目的是 传递点击的【分类或商区的子标题button】文字
    - (void)subTitleImgView:(SubTitleImgView *)subTitleImgView btnClicked:(NSString *)btnTitle
    {
        [MetaDataTool sharedMetaDataTool].currentDistrictName = btnTitle;
    }
    // 难点??

    ? 得到并推断当前button是否选中的文字(比方分类菜单,就返回当前选中的分类名称。区域菜单,就返回当前选中的区域名称) - (NSString *)subTitleImgViewGetCurrentBtnTitle:(SubTitleImgView *)subTitleImgView { // 假设SubTileImgView的代理是DistrictPopMenu,说明应该从工具类返回currentDistrictName给SubTileImgView return [MetaDataTool sharedMetaDataTool].currentDistrictName; } // 顶部菜单由于要改变其三个button的文字,因此在通知中心注冊成为了监听者,因此dealloc时要在通知中心,移除掉监听者 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } @end





    子类:DistrictPopMenuItem

    //
    //  DistrictPopMenuItem.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  如海淀区
    
    #import "PopMenuItem.h"
    @class District;
    @interface DistrictPopMenuItem : PopMenuItem
    
    // 数据源  一个PopMenuItem相应一个商区,如海淀区
    @property (nonatomic, strong) District *district;
    @end
    

    //
    //  DistrictPopMenuItem.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  如海淀区
    
    #import "DistrictPopMenuItem.h"
    #import "District.h"
    @implementation DistrictPopMenuItem
    
    - (void)setDistrict:(District *)district
    {
        _district = district;
        
        [self setTitle:district.name forState:UIControlStateNormal];
    }
    
    // 父类的方法,供子类实现
    // 数据源,子标题数组,全部子标题的名字组成的数组,  本接口,专门交给子类实现
    // 比方 美食 以下有多少个subCategory
    // 比方 海淀区 以下有多少个place
    - (NSArray *)subTitlesArr
    {
        return _district.places;
    }
    
    @end
    

    子类:OrderPopMenu

    //
    //  OrderPopMenu.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
    
    #import "PopMenu.h"
    
    @interface OrderPopMenu : PopMenu
    
    @end
    

    //
    //  OrderPopMenu.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
    
    #import "OrderPopMenu.h"
    #import "OrderPopMenuItem.h"
    #import "Order.h"
    #import "MetaDataTool.h"
    @implementation OrderPopMenu
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 1.往UIScrollView加入内容
            NSArray *orders = [MetaDataTool sharedMetaDataTool].AllOrdersArr;
            int count = orders.count;
            
            for (int i = 0; i<count; i++) {
                // 创建排序item
                OrderPopMenuItem *item = [[OrderPopMenuItem alloc] init];
                item.order = orders[i];
                [item addTarget:self action:@selector(popMenuItemClicked:) forControlEvents:UIControlEventTouchUpInside];
                item.frame = CGRectMake(i * kBottomMenuItemW, 0, 0, 0);
                [_scrollView addSubview:item];
                
                // 默认选中第0个item
                if (i == 0) {
                    item.selected = YES;
                    _selectedPopMenuItem = item;
                }
            }
            _scrollView.contentSize = CGSizeMake(count * kBottomMenuItemW, 0);
        }
        return self;
    }
    @end
    



    子类:OrderPopMenuItem

    //
    //  OrderPopMenuItem.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
    
    #import "PopMenuItem.h"
    @class Order;
    @interface OrderPopMenuItem : PopMenuItem
    
    
    @property (nonatomic, strong) Order *order;
    @end
    

    //
    //  OrderPopMenuItem.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-16.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
    
    #import "OrderPopMenuItem.h"
    #import "Order.h"
    @implementation OrderPopMenuItem
    
    
    - (void)setOrder:(Order *)order
    {
        _order = order;
        
        [self setTitle:order.name forState:UIControlStateNormal];
    }
    @end
    

    最重要的一个工具类

    //
    //  MetaDataTool.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-14.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  元数据管理类
    // 1.城市数据
    // 2.下属分区数据
    // 3.分类数据
    
    #import <Foundation/Foundation.h>
    @class Order;
    @class City;
    @interface MetaDataTool : NSObject
    singleton_interface(MetaDataTool)
    
    
    
    
    // readonly仅仅可读,NSArray,不同意外部随便增删改
    // 全部的城市分组数组,数组中的元素是section对象
    @property (nonatomic, strong, readonly) NSMutableArray *allSectionsArr;
    
    // 全部城市字典,Key是城市名,Value是城市对象
    @property (nonatomic, strong, readonly) NSMutableDictionary *allCitiesDict;
    
    // 当前选中的城市, 当点击了控制器下方的tableView的某一行时,会设置当前城市,拦截setter操作,更新近期訪问的城市数组
    @property (nonatomic, strong) City *currentCity; // 当前选中的城市
    
    
    
    
    
    
    // 全部的分类对象组成的数组,一个分类对象包含分类名,图标,全部子分类名组成的数组
    @property (nonatomic, strong, readonly) NSArray *allCategoriesArr;
    
    // 全部的排序对象组成的数组
    @property (nonatomic, strong, readonly) NSArray *AllOrdersArr;
    
    
    @property (nonatomic, strong) NSString *currentCategoryName; // 当前选中的类别的名字
    @property (nonatomic, strong) NSString *currentDistrictName; // 当前选中的区域名字
    @property (nonatomic, strong) Order *currentOrder; // 当前选中的排序对象
    
    
    // 通过button上面的名字如(价格最高),到MyOrder对象数组中,遍历返回MyOder对象
    - (Order *)orderWithName:(NSString *)name;
    
     
    
    @end
    


    //
    //  MetaDataTool.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-14.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  元数据管理类
    // 1.城市数据
    // 2.下属分区数据
    // 3.分类数据
    
    #import "MetaDataTool.h"
    // 一个分组模型
    #import "Section.h"
    #import "City.h"
    
    // 一个分类对象模型
    #import "MyCategory.h"
    #import "Order.h"
    // 沙盒里面放的是全部以前訪问过的城市名字
    #define kFilePath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"visitedCityNamesArr.data"]
    @interface MetaDataTool ()
    {
        // 数组,存储以前訪问过城市的名称
        NSMutableArray *_visitedCityNamesArr;
        // 訪问过的组section
        Section *_visitedSection; // 近期訪问的城市组数组
    }
    
    @end
    
    @implementation MetaDataTool
    singleton_implementation(MetaDataTool)
    
    
    
    - (id)init
    {
        if (self = [super init]) {
            // 初始化项目中的全部元数据
            
            // 1.初始化城市数据
            
            [self loadCitiesData];
            
            // 2.初始化分类数据
            [self loadCategoryData];
            
            // 3.初始化排序对象数据
            [self loadOrderData];
        }
        return self;
    }
    
    // 1.初始化城市数据
    - (void)loadCitiesData
    {
        // 全部城市对象组成的字典,Key是城市名,Value是城市对象
        _allCitiesDict = [NSMutableDictionary dictionary];
        // 暂时变量,存放全部的section
        NSMutableArray *tempSectionsArr = [NSMutableArray array];
        
        // 1.创建一个热门城市分组
        Section *hotSection = [[Section alloc] init];
        // 组名是 热门
        hotSection.name = @"热门";
        // 分组的成员cities,初始化
        hotSection.cities = [NSMutableArray array];
        // 为了将热门这一组加在分组数组的最前面,准备了一个暂时的section数组
        [tempSectionsArr addObject:hotSection];
        
        // 2.加入A-Z分组,到暂时section数组后面
        // 载入plist数据
        NSArray *sectionsArr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Cities.plist" ofType:nil]];
        for (NSDictionary *dict in sectionsArr) {
            // 创建城市分组对象模型
            Section *section = [[Section alloc] init];
            // 调用分类方法,将字典转成模型
            [section setValuesWithDict:dict];
            // 将全部的section对象,加到暂时的section对象数组的后面
            [tempSectionsArr addObject:section];
            
            // 遍历每一组的全部城市,找出热门的加到hotSection里面
            for (City *city in section.cities) {
                if (city.hot) {
                    // 假设是热门城市
                    [hotSection.cities addObject:city];
                }
                // 而且将全部的城市对象,以城市名作为键,存入字典中
                [_allCitiesDict setObject:city forKey:city.name];
            }
        }
        
        // 3.从沙盒中读取之前訪问过的城市名称
        _visitedCityNamesArr = [NSKeyedUnarchiver unarchiveObjectWithFile:kFilePath];
        // 假设是首次使用,则沙盒中返回的是空数组,须要懒载入,创建一个数组
        if (_visitedCityNamesArr == nil) {
            _visitedCityNamesArr = [NSMutableArray array];
        }
        
        // 4.创建并加入一个section, 近期訪问城市组(section)
        _visitedSection = [[Section alloc] init];
        _visitedSection.name = @"近期訪问";
        _visitedSection.cities = [NSMutableArray array];
        
        // 5.遍历沙盒中取出来的城市名组成的数组,转成一个个城市对象
        for (NSString *name in _visitedCityNamesArr) {
            // 依据城市名,从对象字典中取出城市对象,并加入到近期訪问城市组(section)中的城市对象数组
            City *city = _allCitiesDict[name];
            [_visitedSection.cities addObject:city];
        }
        // 6.假设近期訪问城市组(section)中的城市对象数组中有城市,那么就能够将近期訪问组插入到sections最前面
        if (_visitedSection.cities.count) {
            [tempSectionsArr insertObject:_visitedSection atIndex:0];
        }
        
        // 将全部的section组成的数组赋值给成员变量供调用者訪问
        _allSectionsArr = tempSectionsArr;
    }
    // 当点击了控制器下方的tableView的某一行时,会设置当前城市,拦截setter操作,更新近期訪问的城市数组
    - (void)setCurrentCity:(City *)currentCity
    {
        _currentCity = currentCity;
    
        // 改动当前选中的区域
    //    _currentDistrict = kAllDistrict;
    
        // 1.先从近期訪问的城市名数组中,移除该的城市名
        [_visitedCityNamesArr removeObject:currentCity.name];
    
        // 2.再将新的城市名插入到数组的最前面(近期訪问的在最前)
        [_visitedCityNamesArr insertObject:currentCity.name atIndex:0];
    
        // 3.同一时候,要将新的城市对象,放到_visitedSection的城市对象数组的最前面
        [_visitedSection.cities removeObject:currentCity];
        [_visitedSection.cities insertObject:currentCity atIndex:0];
    
        // 4.归档近期訪问的城市名组成的数组,以便下次再解档
        [NSKeyedArchiver archiveRootObject:_visitedCityNamesArr toFile:kFilePath];
    
        // 5.每一次点击,拦截setter当前城市之后,都要发出通知,做什么用???
        [[NSNotificationCenter defaultCenter] postNotificationName:kCityChangeNote object:nil];
    
        // 6.当用点击了某一行,来到了这个setCurrentCity方法时,肯定是要在最前面,加入“近期訪问组”了
        // 假设 allSectionsArr 已经有了 【近期訪问组】,则不用再加入了
        if (![_allSectionsArr containsObject:_visitedSection]) {
            [_allSectionsArr insertObject:_visitedSection atIndex:0];
        }
    }
    
    // 3.初始化排序对象数组
    - (void)loadOrderData
    {
        NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Orders.plist" ofType:nil]];
        int count = array.count;
        NSMutableArray *temp = [NSMutableArray array];
        for (int i = 0; i<count; i++){
            Order *o = [[Order alloc] init];
            // 设置MyOrder对象的名字
            o.name = array[i];
            // 设置MyOrder对象的索引 1 2 3 4 ...
            o.index = i + 1;
            [temp addObject:o];
        }
        // 全部的排序对象组成的数组
        _AllOrdersArr = temp;
    }
    // 点击PopMenuItem时,可通过button上面的名字如(价格最高),到MyOrder对象数组中,遍历返回MyOder对象,以达到为本工具类设置成员currentOrder的目的
    - (Order *)orderWithName:(NSString *)name
    {
        for (Order *order in _AllOrdersArr) {
            if ([name isEqualToString:order.name]) {
                return order;
            }
        }
        return nil;
    }
     
    
    // 2.初始化分类数据
    - (void)loadCategoryData
    {
        NSMutableArray *tempArr = [NSMutableArray array];
        // 从plist返回的字典数组
        NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Categories.plist" ofType:nil]];
        // 第1个对象是----名字叫:全部分类,无子分类,图标是:
        MyCategory *all = [[MyCategory alloc] init];
        all.name = kAllCategory;
        all.icon = @"ic_filter_category_-1.png";
        [tempArr addObject:all];
        
        // 1.加入全部分类
        // 遍历字典,将字典转成对象模型
        for (NSDictionary *dict in array) {
            MyCategory *c = [[MyCategory alloc] init];
            // 分类方法
            [c setValuesWithDict:dict];
            [tempArr addObject:c];
        }
        
        _allCategoriesArr = tempArr;
    }
    
    
    #pragma mark - 当点击了PopMenuItem的不论什么子类时,都会来到这种方法
    // 设置当前的分类或商区或排序,并发出通知,通知那些须要做出对应的显示改变的东东,比如TopMenu,比如DealListController发送对应的请求,显示对应的查询的内容
    - (void)setCurrentCategoryName:(NSString *)currentCategoryName
    {
        _currentCategoryName = currentCategoryName;
        // 发出通知
        [[NSNotificationCenter defaultCenter] postNotificationName:kCategoryChangeNote object:nil];
    }
    
    - (void)setCurrentDistrictName:(NSString *)currentDistrictName
    {
        _currentDistrictName = currentDistrictName;
        // 发出通知
        [[NSNotificationCenter defaultCenter] postNotificationName:kDistrictChangeNote object:nil];
    }
    
    - (void)setCurrentOrder:(Order *)currentOrder
    {
        _currentOrder = currentOrder;
        // 发出通知
        [[NSNotificationCenter defaultCenter] postNotificationName:kOrderChangeNote object:nil];
    }
    
    @end
    






    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    Nginx日志定时切割脚本
    阿里大于短信接口
    阿里云Linux系统挂载数据盘
    阿里云 OSS+CDN
    值得一学的几条谷歌搜索技巧
    【转】makefile语法规则
    【转】GCC使用简介
    网络编程中常见地址结构与转换(IPv4/IPv6)
    【转】adns解析库——域名解析实例(C++、linux)
    【转】什么是自动化测试
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4625927.html
Copyright © 2020-2023  润新知