广

IOS开发

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

    iOS开发之级联界面(推荐界面)搭建原理

    2018-04-08 09:03:38 次阅读 稿源:互联网
    零七广告

    先看看效果图:

    一.整体布局
     1.项目需求
     点击左边cell,右边的cell数据更新
     2.界面搭建
     2.1交给两个控制器管理比较麻烦,点击一个控制器需要通知另外一个控制器
     2. 2因此交给一个控制器管理比较好
     2.3用xib搭建,左右各放一个tableView就可以了
     3.开发顺序
    先做左边的tableView,再做右边的,因为右边的数据是根据左边变化的

     二.左边tableView界面搭建
     1.自定义cell
     左边一个指示器欧一个view   中间位置用label
     2.设置数据源
      两个tableView设置同一个控制器为数据源和代理,实现方法的时候要先判断tableView的类型
     3.请求数据,查看接口文档
     4.字典转模型
     5.显示数据
     6.运行发现一个tableView顶部被挡住,另一个没被挡住,为什么?
     苹果默认只给界面上一个scrollView设置额外滚动区域,只需要取消自动设置的额外滚动区域,自己手动设置就可以了
     7.选中cell,让cell的指示器显示
     7.1 怎么实现?
     监听cell选中,选中就让指示器显示
     7.2 但是还要监听取消选中,把指示器隐藏
     7.3 怎么同时监听一个cell被选中,另一个cell取消选中?
     cell自己有一个方法可以同时监听 

    // 调用时刻:当一个cell选中的时候就会调用,并且一个cell取消选中的时候也会调用 - (void)setSelected:(BOOL)selected animated:(BOOL)animated 

    7.4 cell不需要选中状态
    self.selectionStyle = UITableViewCellSelectionStyleNone; 

    8.点击左边cell的时候,请求右边tableView的数据
    监听左边cell的点击,然后发送网络请求,请求右边的数据

    三.右边tableView界面搭建
    1.xib复用
     xib也能复用,当两个界面的xib一样时,可以用同一个xib,只要给xib传递不同的模型即可
    2.右边tableView业务逻辑
    3.点击左边的cell,发送网络请求,请求右边的数据
    4.请求数据,查看接口文档
    4.1发现有一个参数category_id 需要根据左边服务器返回的id 来加载右边的数据,所以,我们在左边tableView的模型中要再加一个id属性
    4.2复用模型,模型也能复用,只需要在原来模型中添加需要数据的属性即可
    5.展示数据,点击左边cell,右边就显示对应的数据

    四.整体数据优化
    1.默认选中左边的第0个cell 

     代码如下:
    - (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;  

    2.默认选中第0个cell.写在哪里?
    2.1写在viewDidLoad里面?
    不可以,这个时候还没有数据
    2.2要写在数据加载成功,而且刷新表格之后 

    刷新代码: 

    [self.categoryTableView reloadData]; // 默认选中第0个cellNSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];[self.categoryTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; 

    3.手动选中左边第0个cell,发现右边数据没刷新

    3.1为什么?

    因为 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath方法必须用户手动点击cell才会触发

    3.2怎么解决?
    自己去调用这个方法,写在默认选中第0个cell后边就可以了 

    [self tableView:self.categoryTableView didSelectRowAtIndexPath:indexPath]; 

    4.数据优化
    4.1每次点击左边cell,右边cell都需要发送请求获得数据,消耗性能
    4.2如果加载过一次,就保存起来,下次就不用再加载了。
    4.3保存到哪里?
    保存到对应的分类模型的用户数组里面,在分类tableView的模型中定义一个用户数组,保存左边cell对应的右边的tableView的数据
    4.4 怎么拿到左边cell对应的一组模型?
    请求右边数据的时候,左边对应的cell一定是被选中的,通过记录选中cell对应的模型,就能拿到这个模型
    4.5 在选中左侧cell的方法中,先判断模型中user数组(右边对应的数据数组)是否有值
    如果有值,直接刷新表格,然后return,就不在发送网络请求
    如果没有,就发送网络请求,请求成功后,保存数据,刷新表格,展示数据

    五.上下拉刷新 
    1.项目需求: 右边的tableView需要上下拉刷新功能
    2.怎么实现上下拉刷新?
    使用 MJRefresh框架
    3.下拉刷新,直接加载最新数据,覆盖掉原来的就可以了
    我们原本就是直接用模型中的数组,覆盖掉原来的数据,所以就不用做移除原来数据的处理了
    4.上拉刷新业务逻辑
    4.1上拉刷新,需要加载更多的数据,怎么加载更多的数据?
    需要一个参数(page 或 ID),来获得更多的数据
    4.2这个参数(page)服务器会返回,我们需要记录一下,记录到哪里?
     应该记录到左边tableView的模型中,请求更多数据的时候,从模型中取出这个参数发送请求
     4.3 下拉刷新的时候,要对page参数还原
    把page重置为1,否则下拉刷新,会加载其它页码的数据,到值数据错乱
    4.4 加载更多数据成功的时候,我们就要对page +1,因为记录的page  会作为下次请求参数传递
    注意:只要请求数据,请求成功的时候,就要对page + 1
     4.5 上拉刷新,对数据的处理
    上拉刷新,需要把原来的数据和新加载的数据一起显示
    4.6 怎么一起显示?
    用数组保存加载的更多数据,把这个数组中的元素添加到原来数据数组中
    4.7,怎么把一个数组中的元素,添加到另一个数组中?
    通过- (void)addObject:(ObjectType)anObject;方法?
    不可以,这个方法会把整个数组作为一个元素,添加到另一个数组中[_selectCategoryItem.users addObject:users];
    4.8.那用哪个方法? 

      - (void)addObjectsFromArray:(NSArray<ObjectType> *)otherArray;  

    这个方法会把数组中的每一个元素取出来,添加到另一个数组中
    5.上拉刷新细节处理
    5.1 当没有更多数据的时候,需要隐藏上拉刷新控件
    5.2 怎么隐藏?
     拿到控件设置hidden属性  self.userTableView.mj_footer.hidden
    5.3隐藏的条件是什么?
    需要判断当前用户组,有没有更多用户
    5.4 怎么判断?
    服务器返回的数据有一个 total_page属性,如果当前页>= total_page就没有更多数据
    5.5需要保存 total_page属性,保存到哪里?
    保存到左边tableView的模型中,每次请求成功,就把 total_page属性保存到对应的用户组中
    5.6 在刷新表格的时候,当前的page属性是  当前页数+ 1 的值
    所以设置上拉刷新隐藏的条件应该是 : page > total_page
    5.7 隐藏代码写在哪里?
    写在刷新表格之后,MJ刷新框架每次刷新完数据,会自动判断是否隐藏,一定要在刷新方法后设置才有用
    5.8 每次点击左边cell的时候,也要判断是否隐藏上拉刷新控件,为什么?
    有可能数据只有一页,不判断的话,就会显示上拉刷新控件,去刷新的时候,拿不到更多数据

    源代码

    - (void)viewDidLoad { [super viewDidLoad];  self.title = @"推荐关注"; self.automaticallyAdjustsScrollViewInsets = NO; _categoryTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); _userTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); // 分类tableView注册cell [_categoryTableView registerNib:[UINib nibWithNibName:@"XMGCategoryCell" bundle:nil] forCellReuseIdentifier:categoryID]; // 用户tableView注册cell [_userTableView registerNib:[UINib nibWithNibName:@"XMGSubTagCell" bundle:nil] forCellReuseIdentifier:userID]; // 请求分类数据 [self loadCategoryData]; // 添加上下拉刷新 [self setupRefreshView]; }- (void)setupRefreshView{ // 下拉刷新 // 当松手,并且下拉刷新完全显示的时候,就会触发下拉刷新 MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewUserData)]; header.automaticallyChangeAlpha = YES; self.userTableView.mj_header = header;  // 上拉刷新 MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreUserData)]; footer.automaticallyHidden = YES; self.userTableView.mj_footer = footer;} - (void)loadCategoryData{ AFHTTPSessionManager *mgr = [AFHTTPSessionManager xmg_manager];  NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"category"; parameters[@"c"] = @"subscribe";  [mgr GET:XMGBaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseobject) { NSArray *dictArr = responseobject[@"list"];  _categorys = [XMGCategoryItem mj_objectArrayWithKeyValuesArray:dictArr];  [self.categoryTableView reloadData];  // 默认选中第0个cell NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.categoryTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];  [self tableView:self.categoryTableView didSelectRowAtIndexPath:indexPath];  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  }];}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ if (tableView == _categoryTableView) { // 显示分类TableView return _categorys.count; } return _selectCategoryItem.users.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ if (tableView == _categoryTableView) { // 显示分类TableView XMGCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:categoryID]; cell.item = _categorys[indexPath.row]; return cell; }  XMGSubTagCell *cell = [tableView dequeueReusableCellWithIdentifier:userID]; cell.user = _selectCategoryItem.users[indexPath.row]; return cell;} - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ if (tableView == _categoryTableView) { return 44; } return 60 + 1;}// 点击cell就会调用// 必须用户手动点击cell才会触发- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ if (tableView == _categoryTableView) { // 记录选中分类模型 _selectCategoryItem = _categorys[indexPath.row]; // 点击分类cell // 判断之前有没有数据 if (_selectCategoryItem.users.count) {  [self.userTableView reloadData];  self.userTableView.mj_footer.hidden = _selectCategoryItem.page > _selectCategoryItem.total_page;   return; } // 请求右边用户数据 [self loadNewUserData];  } }// 没有更多数据的时候,隐藏上拉刷新控件// 判断当前分类用户组 有没有更多用户组// 加载更多用户数据- (void)loadMoreUserData{ [self.mgr.tasks makeObjectsPerformSelector:@selector(cancel)];  NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"list"; parameters[@"c"] = @"subscribe"; parameters[@"category_id"] = _selectCategoryItem.id; parameters[@"page"] = @(_selectCategoryItem.page);  [self.mgr GET:XMGBaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseobject) {  [self.userTableView.mj_footer endRefreshing];  _selectCategoryItem.page++; NSArray *dictArr = responseobject[@"list"];  NSArray *users = [XMGUserItem mj_objectArrayWithKeyValuesArray:dictArr];  // 取出数组中所有元素,添加到新数组// [_selectCategoryItem.users addObject:users]; [_selectCategoryItem.users addObjectsFromArray:users];  [self.userTableView reloadData];  // 控制上拉控件是否显示,一定要在reloadData之后 self.userTableView.mj_footer.hidden = _selectCategoryItem.page > _selectCategoryItem.total_page; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  }];}// 加载更新用户数据- (void)loadNewUserData{ _selectCategoryItem.page = 1; [self.mgr.tasks makeObjectsPerformSelector:@selector(cancel)];  NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"list"; parameters[@"c"] = @"subscribe"; parameters[@"category_id"] = _selectCategoryItem.id;  [self.mgr GET:XMGBaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseobject) {  _selectCategoryItem.page++;  // 记录当前分类总页码数 _selectCategoryItem.total_page = [responseobject[@"total_page"] integerValue];  // 结束刷新 [self.userTableView.mj_header endRefreshing];  NSArray *dictArr = responseobject[@"list"];  _selectCategoryItem.users = [XMGUserItem mj_objectArrayWithKeyValuesArray:dictArr];  [self.userTableView reloadData];  self.userTableView.mj_footer.hidden = _selectCategoryItem.page > _selectCategoryItem.total_page;  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  }];}

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    零七网部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与零七网进行文章共享合作。

    零七广告
    零七广告
    零七广告
    零七广告