iOS開發 - 一個天真的搜索控制器的獨白

文/Azen(簡書做者)
原文連接:http://www.jianshu.com/p/6d5327111511
著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。

正文


1、關於橫向模塊開發

團隊型項目開發中,每每是根據功能模塊進行開發任務分工的,如:商品模塊、社交模塊、設置模塊等等,可是模塊與模塊之間,每每存在着一些橫向的、通用的小功能,如:日曆選擇、出發地選擇以及本文要談到的搜索控制器。
作橫向模塊和封裝框架是同樣同樣的,最最重要的,是接口的設計。如何加強模塊的通用性、減小侵入性,讓該模塊的使用者用的爽,在設計接口的時候須要充分考慮的。git

  • 所謂通用性,是指能在多大程度上讓別人用。作的最好的應該是蘋果的UITableView。UITableView被稱爲「SB控件」,由於他不用知道本身展現什麼內容,不用知道本身須要展現多少行,一切差別化的東西,所有經過代理來獲取,因此他能擁有極其強大的通用性,全部想要作表格型展現的人都能用。github

    • 然而,通用性也有它的弊端,就是會額外增長使用該控件的開發人員的工做量。
    • 假設項目中用到的全部tableView,都有相同的tableHeaderView、相同的numberOfSection & numberOfRow。若是仍是用官方原生的UITableView,那咱們每次使用,都須要寫相同的、重複的代碼來設置。
    • 這個時候咱們就應該經過二次封裝的方式,主動下降通用性,來減小重複代碼。
    • 因此,不論是產品仍是技術,沒有絕對好的方案,只有在必定範圍內,最適用的方案。技術就是權衡。
  • 所謂侵入性,是指別人用了你的控件,一旦不想繼續用了,要花費的調整代碼的精力會不會很是大。推薦傑哥的MJExtension,這個神同樣的框架基本上作到了零侵入性。數組

OK,裝B完畢,我們來看看這個「搜索控制器」的需求。緩存

2、需求

  1. 不一樣板塊相同需求
    1.1 右上角的「搜索」按鈕title,沒輸入關鍵詞,展現「取消」;輸入了關鍵詞,展現「搜索」
    1.2 沒搜索到結果,關鍵詞高亮現實

    統一:搜索無結果.gif

    1.3 搜索有結果,展現搜索結果
    1.4 請求數據時,轉菊花
  2. 不一樣板塊不一樣需求
    2.1 板塊一

    板塊一:剛進來沒點搜索.gif

    2.2 板塊二

    板塊二:剛進來沒點搜索.gif

    2.3 板塊三

    板塊三:剛進來沒點搜索.gif

3、思考

問題:

  • UI層面,不一樣的元素如何如何處理?
    • 如:搜索框的placeHolder,是讓使用者傳字符串進來?仍是傳type進來,咱們根據傳進來的type,在控制器內設置不一樣placeholder?
  • 數據層面,請求數據的邏輯在搜索控制器內部寫死?仍是讓外部把搜索結果傳進來?網絡

  • 其餘框架

    • 接口方法設計爲相似MBProgressHUD的「+ (void)showXXXXX」型,仍是設計成普通的返回一個實例控制器,讓使用者決定什麼時候彈出該控制器?

結論

  • UI層面的差別比較簡單明瞭,不涉及到後續一些東西,在控制器內部設置比較方便,採用傳入type方式
  • 數據層面的東西(包括網絡請求和本地持久化),邏輯不那麼簡單直接,並且不一樣板塊應該請求哪些接口、本地存儲存在什麼地方,顯然負責作該板塊的同窗比咱們更清楚,因此最好的辦法是把請求數據之類的事情交給外部去作,咱們只要提供一個方法,讓外部能把請求好的數據轉換成字符串數組傳進來,咱們負責展現就好。
  • "+ (void)showXXX"方法用起來顯然更爽,並且咱們不會把過多的細節暴漏給該控制器的使用者,能夠限制使用者的權限,防止使用者進行一些不恰當的操做致使崩潰(順便插一句,相對於window來講,mac OS 就是這樣作的。不用關心什麼殺毒軟件、硬盤分區之類的破事兒,寫代碼就安心寫代碼,作設計就安心作設計,系統方面的東西能夠不用關心...這也是macOS用起來更爽的緣由之一)

思路整理

如今,我們想作這樣一個搜索控制器:ide

  1. 足夠封閉,不把搜索控制器對象返還給使用者
  2. 有足夠的通用性,請求數據、數據存儲等事情交給調用者處理,咱們的搜索控制器只負責數據展現
    1.1 這意味着,咱們須要告訴調用者(數據逆傳):spa

    • 何時應該請求網絡數據(點擊了搜索按鈕)
    • 何時應該清空本地緩存(點擊了清除按鈕)
    • 用戶點擊了哪條搜索結果

    1.2 調用者須要告訴咱們(數據順傳):設計

    • 請求回來的數據是什麼
  3. 請注意,一般咱們進行數據順傳的方式,是拿到某個控制器,點出來他的屬性,並進行賦值;而我們想要的效果,是最大程度限制調用者的權限,不讓調用者拿到我們的搜索控制器(意味着不能點出來)的同時,最好限制調用者只能經過我們給定的方法告訴我們搜索結果(不讓調用者拿到搜索控制器的屬性)。3d

怎麼辦?有什麼辦法能不返還給調用者一個對象,只返還給調用者一個方法?答案是block。
數據逆傳方面,我的也仍是很是喜歡block。由於相比於代理,block可以讓代碼實現「高聚合、低耦合」,不用跳來跳去的找代碼,維護起來更方便。
(下一篇:一個複雜的首頁的獨白中,我們會用到將代理和數據源方法,全都變成block的tableView)

4、上代碼吧

這篇文章主要講的,其實仍是接口設計。因此代碼就只貼頭文件吧,源碼丟在Github上了嗯(源碼傳送門)...若是以爲還有那麼點小啓發的話,記得順手點星哦^_^

 1 文/Azen(簡書做者)
 2 原文連接:http://www.jianshu.com/p/6d5327111511
 3 著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。
 4 
 5 //
 6 //  AZXSearchController.h
 7 //  AZXSearchControllerDemo
 8 //
 9 //  Created by Azen.Xu on 15/12/5.
10 //  Copyright © 2015年 Azen.Xu. All rights reserved.
11 //
12 
13 #import <UIKit/UIKit.h>
14 
15 typedef NS_ENUM(NSInteger, AZXSearchControllerType) //  搜索控制器類型
16 {
17     AZXSearchControllerTypePartOne = 1 << 0,   //  板塊一
18     AZXSearchControllerTypePartTwo = 1 << 1,   //  板塊二
19     AZXSearchControllerTypePartThree = 1 << 2  //  板塊三
20 };
21 
22 typedef NS_ENUM(NSInteger, AZXSearchFunctionType)   //  點擊事件類型
23 {
24     AZXSearchFunctionTypeClear = 1 << 0,    //  點擊了"清除搜索歷史"按鈕
25     AZXSearchFunctionTypeSearch = 1 << 1,   //  點擊了"搜索"按鈕
26     AZXSearchFunctionTypeSearchArray = 1 << 2,    //  點選了搜索結果列表
27     AZXSearchFunctionTypeHotArray = 1 << 3,       //  點選了熱門搜索列表
28     AZXSearchFunctionTypeHistoryArray = 1 << 4,   //  點選了歷史搜索列表
29     AZXSearchFunctionTypeCreatTagForDiscover = 1 << 5   //  點選了建立標籤
30 };
31 
32 typedef void(^AZXSearchCallBack)(AZXSearchFunctionType selectedType , NSInteger selectedRowIndex , NSString *resultString); //  點擊回調 參數一:點擊事件類型 參數二:選中行號 參數三:選中文字
33 typedef void(^AZXSearchSetNewArrayHandle)(NSArray *newArray);   //  經過此block傳遞搜索結果字符串數組
34 
35 
36 @interface AZXSearchController : UIViewController
37 
38 /**
39  *  根據type建立不一樣展現樣式的搜索控制器,返回搜索結果handleArray
40  *
41  *  @param fromController 來源控制器
42  *  @param hotArray       熱門搜索stringArray
43  *  @param hisArray       歷史搜索stringArray
44  *  @param type           樣式枚舉
45  *  @param calBack        回調 - 數據請求成功後請爲handleStringArray從新賦值
46  *
47  *  @return 搜索結果handelArray
48  */
49 + (AZXSearchSetNewArrayHandle)showSearchControllerFromController :(UIViewController *)fromController
50                                                withHotModelArray :(NSArray *)hotArray
51                                                    hisModelArray :(NSArray *)hisArray
52                                                             type :(AZXSearchControllerType)type
53                                                         callBack :(AZXSearchCallBack)callBack;
54 
55 @end
View Code
相關文章
相關標籤/搜索