您好,登錄后才能下訂單哦!
這篇文章主要為大家詳細介紹了iOS客戶端開發中搜索功能的方法,文中示例代碼介紹的非常詳細,圖文詳解容易學習,非常適合初學者入門,感興趣的小伙伴們可以參考一下。
在軟件首頁右上角有一個搜索按鈕,點擊進入搜索界面,當搜索的內容很多時我們下拉點擊 “下面20項。。。”可以在加載20項,這些數據如何填充到表視圖之中?
負責搜索功能的是search下的searchView類,xib控件已經已經做好布局,首先說下SearchView.h文件屬性成員代表的作用;
#import <UIKit/UIKit.h> #import "SearchResult.h" #import "MBProgressHUD.h" @interface SearchView : UIViewController<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate> { // 可變數組存放解析的數據 NSMutableArray * results; // 搜索的時候判斷是否正在加載數據 BOOL isLoading; // 判斷數據是否加載完畢 BOOL isLoadOver; // 記錄表視圖單元格應該加載數據總條數 int allCount; } @property (strong, nonatomic) IBOutlet UISegmentedControl *segmentSearch; @property (strong, nonatomic) IBOutlet UITableView *tableResult; @property (strong, nonatomic) IBOutlet UISearchBar *_searchBar; //根據搜索關鍵字在不同分類中進行搜索 - (IBAction)segementChanged:(id)sender; //搜索 -(void)doSearch; //清空上次搜索記錄 -(void)clear;
OK現在看看SearchView.m文件,如果搜索的內容不為空開始 dosearch方法,dosearch方法中使用了ASNetwork類庫封裝的post網絡請求方法(關于AFNetwork post get請求方法請看http://blog.csdn.net/duxinfeng2010/article/details/8620901)
- (void)postPath:(NSString *)path parameters:(NSDictionary *)parameters success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
post請求無法獲取它的url,但是可以取出請求成功返回來的數據,比如搜索iOS 返回的xml
<?xml version="1.0" encoding="UTF-8"?> <oschina> <pagesize>20</pagesize> <results> <result> <objid>18397</objid> <type>software</type> <title><![CDATA[iOS應用開發模板 iOS Boilerplate]]></title> <url><![CDATA[http://www.oschina.net/p/ios-boilerplate]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>18977</objid> <type>software</type> <title><![CDATA[ ios-static-libraries]]></title> <url><![CDATA[http://www.oschina.net/p/ios-static-libraries]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>23309</objid> <type>software</type> <title><![CDATA[ 仿陌陌的ios客戶端]]></title> <url><![CDATA[http://www.oschina.net/p/momo-ios-app]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>22121</objid> <type>software</type> <title><![CDATA[iOS任務管理器 cheddar-ios]]></title> <url><![CDATA[http://www.oschina.net/p/cheddar-ios]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>22900</objid> <type>software</type> <title><![CDATA[白宮網站 iOS 客戶端 wh-app-ios]]></title> <url><![CDATA[http://www.oschina.net/p/wh-app-ios]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>17045</objid> <type>software</type> <title><![CDATA[iPhone操作系統 iOS]]></title> <url><![CDATA[http://www.oschina.net/p/ios]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>25685</objid> <type>software</type> <title><![CDATA[iOS 彈出菜單 MLPPopupMenu]]></title> <url><![CDATA[http://www.oschina.net/p/mlppopupmenu]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>22803</objid> <type>software</type> <title><![CDATA[iOS日歷控件 PMCalendar]]></title> <url><![CDATA[http://www.oschina.net/p/pmcalendar]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>24390</objid> <type>software</type> <title><![CDATA[iOS 功能測試框架 calabash-ios]]></title> <url><![CDATA[http://www.oschina.net/p/calabash-ios]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>24665</objid> <type>software</type> <title><![CDATA[ iOS-Tree-Component]]></title> <url><![CDATA[http://www.oschina.net/p/ios-tree-component]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>22217</objid> <type>software</type> <title><![CDATA[ ios-calendar]]></title> <url><![CDATA[http://www.oschina.net/p/ios-calendar]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>22380</objid> <type>software</type> <title><![CDATA[ PaperFold-for-iOS]]></title> <url><![CDATA[http://www.oschina.net/p/paperfold-for-ios]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>21763</objid> <type>software</type> <title><![CDATA[ drupal-ios-sdk]]></title> <url><![CDATA[http://www.oschina.net/p/drupal-ios-sdk]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>19628</objid> <type>software</type> <title><![CDATA[iOS開發基礎工具包 BaseAppKit]]></title> <url><![CDATA[http://www.oschina.net/p/baseappkit]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>20637</objid> <type>software</type> <title><![CDATA[iOS消息提醒庫 TBHintView]]></title> <url><![CDATA[http://www.oschina.net/p/tbhintview]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>21246</objid> <type>software</type> <title><![CDATA[iOS 彈出式菜單 MGTileMenu]]></title> <url><![CDATA[http://www.oschina.net/p/mgtilemenu]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>23498</objid> <type>software</type> <title><![CDATA[iOS 的 Canvas 和 Audio 實現 Ejecta]]></title> <url><![CDATA[http://www.oschina.net/p/ejecta]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>23968</objid> <type>software</type> <title><![CDATA[樣式化 iOS 應用 NUI]]></title> <url><![CDATA[http://www.oschina.net/p/nui]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>20730</objid> <type>software</type> <title><![CDATA[iOS/Android 矢量圖形框架 TouchVG]]></title> <url><![CDATA[http://www.oschina.net/p/touchvg]]></url> <pubDate></pubDate> <author></author> </result> <result> <objid>22356</objid> <type>software</type> <title><![CDATA[iOS日歷控件 MACalendarUI]]></title> <url><![CDATA[http://www.oschina.net/p/macalendarui]]></url> <pubDate></pubDate> <author></author> </result> </results> <notice> <atmeCount>0</atmeCount> <msgCount>0</msgCount> <reviewCount>0</reviewCount> <newFansCount>0</newFansCount> </notice> </oschina> <!-- Generated by OsChina.NET (init:0[ms],page:13[ms],ip:61.163.231.198) -->
要解析xm里數據必須熟悉xml文件各個節點之間關系
根節點oschina,它的子節點pagesize返回本次加載了幾條數據,子節點results,results的子節點下20條result節點,我們主要獲取result內容。然后就是最后面的子節點notice節點,存放用戶的一些信息如動彈情況、收到消息、回復、粉絲;在post請求中用到了一個異常處理語句 @try @catch @finally
@try
{
//執行的代碼,其中可能有異常。一旦發現異常,則立即跳到catch執行。否則不會執行catch里面的內容
}
@catch
{
//除非try里面執行代碼發生了異常,否則這里的代碼不會執行
}
@finally
{
//不管什么情況都會執行,包括try catch 里面用了return ,可以理解為只要執行了try或者catch,就一定會執行 finally
}
給dosearch添加了一些注釋
-(void)doSearch { // 標記,表示正在加載數據中 isLoading = YES; NSString * catalog; // switch語句中根據Segment按鈕集合中按鈕索引,判斷搜索哪一類內容,為下面的搜索API傳參 switch (self.segmentSearch.selectedSegmentIndex) { case 0: catalog = @"software"; break; case 1: catalog = @"post"; break; case 2: catalog = @"blog"; break; case 3: catalog = @"news"; break; } //使用AFNetWork使用post方式從網絡請求數據 [[AFOSCClient sharedClient] postPath:api_search_list parameters:[NSDictionary dictionaryWithObjectsAndKeys:_searchBar.text,@"content",catalog,@"catalog",[NSString stringWithFormat:@"%d", allCount/20],@"pageIndex",@"20",@"pageSize", nil] success:^(AFHTTPRequestOperation *operation, id responseObject) { // 取消searchBar的第一響應對象,鍵盤消失 [self._searchBar resignFirstResponder]; // 在沒有內容之前tableView是沒有任何內容的,所以隱藏掉 self.tableResult.hidden = NO; // 根據請求回來的數據判斷當前用戶釋放登陸,需要獲取用戶一些信息 [Tool getOSCNotice2:operation.responseString]; // 上面屬于請求數據是不回加載到視圖控制器上,所以標記屬性為NO isLoading = NO; // 再次從xml文件中請求數據,獲取當前加載數據條數,數量 int count = [Tool isListOver2:operation.responseString]; allCount += count; // 將請求的xml內容給NSString對象 NSString *response = operation.responseString; NSLog(@"response =%@",response); @try { // 開始解析需要顯示到表視圖單元格對象中的數據 TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil]; TBXMLElement *root = xml.rootXMLElement; // 從次根節點獲取根節點下內容 TBXMLElement *_results = [TBXML childElementNamed:@"results" parentElement:root]; if (!_results) { isLoadOver = YES; [self.tableResult reloadData]; return; } // 獲取result節點下內容 TBXMLElement *first = [TBXML childElementNamed:@"result" parentElement:_results]; if (!first) { isLoadOver = YES; [self.tableResult reloadData]; return; } // 取出result節點下的節點 NSMutableArray * newResults = [[NSMutableArray alloc] initWithCapacity:20]; TBXMLElement *objid = [TBXML childElementNamed:@"objid" parentElement:first]; TBXMLElement *type = [TBXML childElementNamed:@"type" parentElement:first]; TBXMLElement *title = [TBXML childElementNamed:@"title" parentElement:first]; TBXMLElement *url = [TBXML childElementNamed:@"url" parentElement:first]; TBXMLElement *pubDate = [TBXML childElementNamed:@"pubDate" parentElement:first]; NSString * pubDateStr = [TBXML textForElement:pubDate]; TBXMLElement *author = [TBXML childElementNamed:@"author" parentElement:first]; // 取出節點中的值,賦給一個SearchResult對象屬性 SearchResult * s = [[SearchResult alloc] initWithParameters:[[TBXML textForElement:objid] intValue] andType:[[TBXML textForElement:type] intValue] andTitle:[TBXML textForElement:title] andUrl:[TBXML textForElement:url] andPubDate:[pubDateStr isEqualToString:@""] ? @"" : [Tool intervalSinceNow:pubDateStr] andAuthor:[TBXML textForElement:author]]; // 將獲取對象添加到可變數組 if (![Tool isRepeatSearch:results andResult:s]) { [newResults addObject:s]; } // 在循環之中 尋找下一個節點 直至找完 while (first) { first = [TBXML nextSiblingNamed:@"result" searchFromElement:first]; if (first) { objid = [TBXML childElementNamed:@"objid" parentElement:first]; type = [TBXML childElementNamed:@"type" parentElement:first]; title = [TBXML childElementNamed:@"title" parentElement:first]; url = [TBXML childElementNamed:@"url" parentElement:first]; pubDate = [TBXML childElementNamed:@"pubDate" parentElement:first]; author = [TBXML childElementNamed:@"author" parentElement:first]; s = [[SearchResult alloc] initWithParameters:[[TBXML textForElement:objid] intValue] andType:[[TBXML textForElement:type] intValue] andTitle:[TBXML textForElement:title] andUrl:[TBXML textForElement:url] andPubDate:[Tool intervalSinceNow:[TBXML textForElement:pubDate]] andAuthor:[TBXML textForElement:author]]; // if (![Tool isRepeatSearch:results andResult:s]) { [newResults addObject:s]; } } // first = NULL 直接跳出 else { break; } } // 如果搜索結果數據小雨20條,表示一個頁面就可以加載完畢 if (newResults.count < 20) { isLoadOver = YES; } // 將解析數據添加道results之中 [results addObjectsFromArray:newResults]; // 刷新表示圖內容 [self.tableResult reloadData]; } @catch (NSException *exception) { [NdUncaughtExceptionHandler TakeException:exception]; } @finally { } // 請求失敗 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [Tool ToastNotification:@"網絡連接故障" andView:self.view andLoading:NO andIsBottom:NO]; }]; // 刷新表視圖單元內容 [self.tableResult reloadData]; }
在 [Tool getOSCNotice2:operation.responseString];解析的登陸用戶一些信息
// Tool類中
+ (OSCNotice *)getOSCNotice2:(NSString *)response { TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil]; TBXMLElement *root = xml.rootXMLElement; if (!root) { return nil; } TBXMLElement *notice = [TBXML childElementNamed:@"notice" parentElement:root]; if (!notice) { [Config Instance].isLogin = NO; [[NSNotificationCenter defaultCenter] postNotificationName:@"login" object:@"0"]; return nil; } else { [[NSNotificationCenter defaultCenter] postNotificationName:@"login" object:@"1"]; [Config Instance].isLogin = YES; } TBXMLElement *atme = [TBXML childElementNamed:@"atmeCount" parentElement:notice]; TBXMLElement *msg = [TBXML childElementNamed:@"msgCount" parentElement:notice]; TBXMLElement *review = [TBXML childElementNamed:@"reviewCount" parentElement:notice]; TBXMLElement *newFans = [TBXML childElementNamed:@"newFansCount" parentElement:notice]; OSCNotice *oc = [[OSCNotice alloc] initWithParameters:[[TBXML textForElement:atme] intValue] andMsg:[[TBXML textForElement:msg] intValue] andReview:[[TBXML textForElement:review] intValue] andFans:[[TBXML textForElement:newFans] intValue]]; [[NSNotificationCenter defaultCenter] postNotificationName:Notification_NoticeUpdate object:oc]; return oc; }
[Tool isListOver2:operation.responseString]; 用于也是解析數據,獲取返回的數據條數,告訴table將要顯示多少行cell,當把cell加載到最后的時候獲取下面20項,或跟多,然后把這些數據存放道allcount里面,所以就有allCount += count
Tool類中,解析返回一個數據 pagesize,顯示多少行
+ (int)isListOver2:(NSString *)response { TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil]; TBXMLElement *root = xml.rootXMLElement; TBXMLElement *pageSize = [TBXML childElementNamed:@"pagesize" parentElement:root]; int size = [[TBXML textForElement:pageSize] intValue]; return size; }
然后進入到try中又一次解析獲取result里面數據,這里有請求了一次數據,有解析了一邊,感覺這里處理的不是很好,同一個返回數據請求了三次,如果用戶用的不是wifi就可能耗費流量浪費電量;
剩下的就是表示圖加載數據了
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // 如何加載完成,返回數據為空,返回1,這個單元格是顯示一個提示,“查無結果” 如果返回不為空,返回results.count + 1 個顯示結果,最后加 1 ,是顯示加載數據超過20條的時候 點擊 “下面20項”時加載更多數據 if (isLoadOver) { return results.count == 0 ? 1 : results.count; } else return results.count + 1; } //處理cell的行高 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (isLoadOver) { return results.count == 0 ? 62 : 50; } else { return indexPath.row < results.count ? 50 : 62; } } //處理tableView背景色 -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { cell.backgroundColor = [Tool getCellBackgroundColor]; } //定制單元格的顯示內容 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (results.count > 0) { if (indexPath.row < results.count) { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NormalCellIdentifier]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:NormalCellIdentifier]; } SearchResult * s = [results objectAtIndex:indexPath.row]; cell.textLabel.font = [UIFont boldSystemFontOfSize:15.0]; cell.textLabel.text = s.title; if (self.segmentSearch.selectedSegmentIndex != 0) { cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ 發表于 %@", s.author, s.pubDate]; } else { cell.detailTextLabel.text = @""; } cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; return cell; } else { return [[DataSingleton Instance] getLoadMoreCell:tableView andIsLoadOver:isLoadOver andLoadOverString:@"搜索完畢" andLoadingString:(isLoading ? loadingTip : loadNext20Tip) andIsLoading:isLoading]; } } // 如果搜索返回的數據為空 提示 查無結果 else { return [[DataSingleton Instance] getLoadMoreCell:tableView andIsLoadOver:isLoadOver andLoadOverString:@"查無結果" andLoadingString:(isLoading ? loadingTip : loadNext20Tip) andIsLoading:isLoading]; } } //選中某一行的時候顯示該條信息的詳細內容 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self._searchBar resignFirstResponder]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; int row = indexPath.row; if (row >= results.count) { if (!isLoading && !isLoadOver) { [self performSelector:@selector(doSearch)]; } } else { SearchResult * s = [results objectAtIndex:row]; if (s) { [Tool analysis:s.url andNavController:self.navigationController]; NSLog(@"------%@",s.url); } } }
打開某一條信息,并查看其詳細信息調用 analysis: andNavController:,該方法里針對傳入URL,如果是站外連接 比如某個軟件官網,直接跳轉到該軟件的官網上,如果是開源中國社區站內連接,就可能需要加載一些這條信息的評論詳情如果檢測道用戶登陸給予用戶品論權限和分享功能;具體實現如下
+ (BOOL)analysis:(NSString *)url andNavController:(UINavigationController *)navController { NSString *search = @"oschina.net"; //判斷是否包含 oschina.net 來確定是不是站內鏈接 NSRange rng = [url rangeOfString:search]; if (rng.length <= 0) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; return NO; } //站內鏈接 else { url = [url substringFromIndex:7]; NSString *prefix = [url substringToIndex:3]; //此情況為 博客,動彈,個人專頁 if ([prefix isEqualToString:@"my."]) { NSArray *array = [url componentsSeparatedByString:@"/"]; //個人專頁 用戶名形式 if ([array count] <= 2) { [Tool pushUserDetailWithName:[array objectAtIndex:1] andNavController:navController]; return YES; } //個人專頁 uid形式 else if([array count] <= 3) { if ([[array objectAtIndex:1] isEqualToString:@"u"]) { [Tool pushUserDetail:[[array objectAtIndex:2] intValue] andNavController:navController]; return YES; } } else if([array count] <= 4) { NSString *type = [array objectAtIndex:2]; if ([type isEqualToString:@"blog"]) { News *n = [[News alloc] init]; n.newsType = 3; n.p_w_upload = [array objectAtIndex:3]; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:NO]; return YES; } else if([type isEqualToString:@"tweet"]){ Tweet *t = [[Tweet alloc] init]; t._id = [[array objectAtIndex:3] intValue]; [Tool pushTweetDetail:t andNavController:navController]; return YES; } } else if(array.count <= 5) { NSString *type = [array objectAtIndex:3]; if ([type isEqualToString:@"blog"]) { News *n = [[News alloc] init]; n.newsType = 3; n.p_w_upload = [array objectAtIndex:4]; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:NO]; return YES; } } } //此情況為 新聞,軟件,問答 else if([prefix isEqualToString:@"www"]) { NSArray *array = [url componentsSeparatedByString:@"/"]; int count = [array count]; if (count>=3) { NSString *type = [array objectAtIndex:1]; if ([type isEqualToString:@"news"]) { int newsid = [[array objectAtIndex:2] intValue]; News *n = [[News alloc] init]; n.newsType = 0; n._id = newsid; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:YES]; return YES; } else if([type isEqualToString:@"p"]){ News *n = [[News alloc] init]; n.newsType = 1; n.p_w_upload = [array objectAtIndex:2]; [Tool pushNewsDetail:n andNavController:navController andIsNextPage:NO]; return YES; } else if([type isEqualToString:@"question"]){ if (count == 3) { NSArray *array2 = [[array objectAtIndex:2] componentsSeparatedByString:@"_"]; if ([array2 count] >= 2) { int _id = [[array2 objectAtIndex:1] intValue]; Post *p = [[Post alloc] init]; p._id = _id; [Tool pushPostDetail:p andNavController:navController]; return YES; } } else if(count >= 4) { // NSString *tag = [array objectAtIndex:3]; NSString *tag = @""; if (array.count == 4) { tag = [array objectAtIndex:3]; } else { for (int i=3; i<count-1; i++) { tag = [NSString stringWithFormat:@"%@/%@", [array objectAtIndex:i],[array objectAtIndex:i+1]]; } } NSString *tag2 = [tag stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; PostsView *pview = [PostsView new]; pview.tag = tag; pview.navigationItem.title = [NSString stringWithFormat:@"%@", tag2]; [navController pushViewController:pview animated:YES]; return YES; } } } } // 根據一個URL打開一個網頁 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@", url]]]; return NO; } }
以上就是iOS客戶端開發中搜索功能的具體操作,代碼應該是足夠清楚的,而且我也相信有相當的一些例子可能是我們日常工作可能會見得到的。通過這篇文章,希望你能收獲更多。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。