級聯界面(推薦界面)搭建原理

来源:http://www.cnblogs.com/xiaotian666/archive/2016/08/12/5764520.html
-Advertisement-
Play Games

一.整體佈局 一.整體佈局 1.項目需求 點擊左邊cell,右邊的cell數據更新 2.界面搭建 2.1交給兩個控制器管理比較麻煩,點擊一個控制器需要通知另外一個控制器 2. 2因此交給一個控制器管理比較好 2.3用xib搭建,左右各放一個tableView就可以了 3.開發順序 先做左邊的tabl ...


 

 


一.整體佈局

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自己有一個方法可以同時監聽
1 // 調用時刻:當一個cell選中的時候就會調用,並且一個cell取消選中的時候也會調用
2 - (void)setSelected:(BOOL)selected animated:(BOOL)animated 

 

       7.4 cell不需要選中狀態  
1     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
1 - (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
  2.預設選中第0個cell.寫在哪裡?      2.1寫在viewDidLoad裡面?           不可以,這個時候還沒有數據        2.2要寫在數據載入成功,而且刷新表格之後 刷新代碼:
1   [self.categoryTableView reloadData]; 
2     // 預設選中第0個cell
3    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
4    [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後邊就可以了
1  [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.那用哪個方法?
1    - (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的時候,也要判斷是否隱藏上拉刷新控制項,為什麼?           有可能數據只有一頁,不判斷的話,就會顯示上拉刷新控制項,去刷新的時候,拿不到更多數據   源代碼
  1 - (void)viewDidLoad {
  2     [super viewDidLoad];
  3  
  4     self.title = @"推薦關註";
  5     self.automaticallyAdjustsScrollViewInsets = NO;
  6     _categoryTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
  7     _userTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
  8     // 分類tableView註冊cell
  9     [_categoryTableView registerNib:[UINib nibWithNibName:@"XMGCategoryCell" bundle:nil] forCellReuseIdentifier:categoryID];
 10     // 用戶tableView註冊cell
 11     [_userTableView registerNib:[UINib nibWithNibName:@"XMGSubTagCell" bundle:nil] forCellReuseIdentifier:userID];
 12     // 請求分類數據
 13     [self loadCategoryData];
 14     // 添加上下拉刷新
 15     [self setupRefreshView];  
 16 }
 17 - (void)setupRefreshView
 18 {
 19     // 下拉刷新
 20     // 當鬆手,並且下拉刷新完全顯示的時候,就會觸發下拉刷新
 21     MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewUserData)];
 22     header.automaticallyChangeAlpha = YES;
 23     self.userTableView.mj_header = header;
 24    
 25     // 上拉刷新
 26     MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreUserData)];
 27     footer.automaticallyHidden = YES;
 28     self.userTableView.mj_footer = footer;
 29 }
 30  
 31 - (void)loadCategoryData
 32 {
 33     AFHTTPSessionManager *mgr = [AFHTTPSessionManager xmg_manager];
 34   
 35     NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
 36     parameters[@"a"] = @"category";
 37     parameters[@"c"] = @"subscribe";
 38    
 39     [mgr GET:XMGBaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) {
 40         NSArray *dictArr = responseObject[@"list"];
 41        
 42         _categorys = [XMGCategoryItem mj_objectArrayWithKeyValuesArray:dictArr];
 43        
 44         [self.categoryTableView reloadData];
 45        
 46         // 預設選中第0個cell
 47         NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
 48         [self.categoryTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
 49        
 50         [self tableView:self.categoryTableView didSelectRowAtIndexPath:indexPath];
 51        
 52     } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  
 53     }];
 54 }
 55 
 56 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 57 {
 58     if (tableView == _categoryTableView) { // 顯示分類TableView
 59         return _categorys.count;
 60     }
 61     return _selectCategoryItem.users.count;
 62 }
 63 
 64 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 65 {
 66     if (tableView == _categoryTableView) { // 顯示分類TableView
 67         XMGCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:categoryID];
 68         cell.item = _categorys[indexPath.row];
 69         return cell;
 70     } 
 71      XMGSubTagCell *cell = [tableView dequeueReusableCellWithIdentifier:userID];
 72      cell.user =  _selectCategoryItem.users[indexPath.row];
 73     return cell;
 74 }
 75  
 76 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 77 {
 78     if (tableView == _categoryTableView) {
 79         return 44;
 80     }
 81     return 60 + 1;
 82 }
 83 // 點擊cell就會調用
 84 // 必須用戶手動點擊cell才會觸發
 85 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 86 {
 87     if (tableView == _categoryTableView) {
 88         // 記錄選中分類模型
 89         _selectCategoryItem = _categorys[indexPath.row];
 90         // 點擊分類cell
 91         // 判斷之前有沒有數據
 92         if (_selectCategoryItem.users.count) {
 93             [self.userTableView reloadData];
 94             self.userTableView.mj_footer.hidden = _selectCategoryItem.page > _selectCategoryItem.total_page;    
 95             return;
 96         }
 97         // 請求右邊用戶數據
 98         [self loadNewUserData];     
 99     }   
100 }
101 
102 // 沒有更多數據的時候,隱藏上拉刷新控制項
103 // 判斷當前分類用戶組 有沒有更多用戶組
104 // 載入更多用戶數據
105 - (void)loadMoreUserData
106 {
107     [self.mgr.tasks makeObjectsPerformSelector:@selector(cancel)];
108    
109     NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
110     parameters[@"a"] = @"list";
111     parameters[@"c"] = @"subscribe";
112     parameters[@"category_id"] = _selectCategoryItem.id;
113     parameters[@"page"] = @(_selectCategoryItem.page);
114    
115     [self.mgr GET:XMGBaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) {
116        
117         [self.userTableView.mj_footer endRefreshing];
118        
119         _selectCategoryItem.page++;
120         NSArray *dictArr = responseObject[@"list"];
121        
122         NSArray *users = [XMGUserItem mj_objectArrayWithKeyValuesArray:dictArr];
123        
124         // 取出數組中所有元素,添加到新數組
125 //        [_selectCategoryItem.users addObject:users];
126         [_selectCategoryItem.users addObjectsFromArray:users];
127        
128         [self.userTableView reloadData];
129        
130         // 控制上拉控制項是否顯示,一定要在reloadData之後
131         self.userTableView.mj_footer.hidden = _selectCategoryItem.page > _selectCategoryItem.total_page;
132     } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {    
133     }];
134 }
135 
136 // 載入更新用戶數據
137 - (void)loadNewUserData
138 {
139     _selectCategoryItem.page = 1;
140     [self.mgr.tasks makeObjectsPerformSelector:@selector(cancel)];
141    
142     NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
143     parameters[@"a"] = @"list";
144     parameters[@"c"] = @"subscribe";
145     parameters[@"category_id"] = _selectCategoryItem.id;
146    
147     [self.mgr GET:XMGBaseUrl parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) {
148        
149         _selectCategoryItem.page++;
150        
151         // 記錄當前分類總頁碼數
152         _selectCategoryItem.total_page = [responseObject[@"total_page"] integerValue];
153        
154         // 結束刷新
155         [self.userTableView.mj_header endRefreshing];
156        
157         NSArray *dictArr = responseObject[@"list"];
158        
159         _selectCategoryItem.users = [XMGUserItem mj_objectArrayWithKeyValuesArray:dictArr];
160        
161         [self.userTableView reloadData];
162        
163         self.userTableView.mj_footer.hidden = _selectCategoryItem.page > _selectCategoryItem.total_page;
164   
165     } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {      
166     }];
167 }

 喜歡就推薦下吧,哈哈

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 打開相機 打開相冊 onActivityResult OtherUtils ...
  • 一.界面搭建 1.確定開發模式 如果界面是固定的,可以用xib 界面的一些內容不固定,就用純代碼 cell用什麼方式去開發(我們採用純代碼和xib結合的方式) 2.劃分層次結構 2.1 怎麼劃分? 按照功能劃分 1.確定開發模式 如果界面是固定的,可以用xib 界面的一些內容不固定,就用純代碼 ce ...
  • Xcode7.2,iOS9.2環境下 嘗試在CollectionViewCell內部,添加LongPress手勢,顯示UIMenuController。 實現以上代碼,就可以在長按cell時顯示出UIMenuController。 註意註意:!!!!!要實現UIMenuItem的綁定方法, 很奇怪的 ...
  • 1:運行React Native報連接錯誤解決 解決方式: 在終端進入項目文件里,然後執行:(cd Pods/React; npm run start) 2:組件生命周期介紹 創建階段 1、 getDefaultProps 作用於組件類,也就是調用React.createClass()的時候被調用。 ...
  • 1.監聽按鈕點擊 2.判斷是否是點擊的同一個按鈕(記錄上次點擊的按鈕) 3.當重覆點擊相同按鈕時,需要獲取當前按鈕對應控制器刷新界面 3.1 判斷是否重覆點擊按鈕,代碼寫在哪裡? 點擊標題按鈕,屬於精華控制器的事情,所以找到精華控制器.寫在點擊按鈕方法裡面 3.2怎麼拿到按鈕對應的控制器? 通過當前 ...
  • 一、簡介 相信大家用eclipse上的模擬器會覺得很慢很卡,這裡給大家介紹個好東西安卓模擬器genymotion。瞭解更多,可到此網站https://www.genymotion.com/。 二、安裝genymotion 1、註冊genymotion登錄帳號 進入網站https://www.geny ...
  • 一.點擊查看大圖 1.點擊圖片或按鈕(點擊查看大圖按鈕),modal出來一個控制器,顯示大圖片 2.怎麼處理能讓點擊圖片就能查看大圖? 兩種方法:1.給圖片添加點按手勢 2.給圖片所在的view上添加 - (void)touchesEnded:(NSSet<UITouch *> *)touches ...
  • 目前市面上的應用,貌似除了微信和手Q都會比較擔心被用戶或者系統(廠商)殺死問題。本文對 Android 進程拉活進行一個總結。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...