由一個自定義分享頁面的需求想到的

一個自定義分享頁面引起的思考

引言

相信絕大多數人都用過或者正使用着UMeng分享,可是每每UMeng提供的分享樣式知足不了咱們的需求,例如咱們想額外填加一些按鈕(複製連接、舉報等)。
目前在作的這個項目一開始是使用的UMeng的分享樣式,準備上架時因爲審覈要求,咱們須要加一個舉報按鈕,因此將"分享"按鈕改成"更多"按鈕,而後須要將舉報放在分享的下面一行,而且查看別人的內容的時候須要顯示舉報,查看本身的內容的時候是不須要顯示舉報按鈕的(誰還須要舉報本身啊,哈哈),因此一個頁面有兩種狀態;
同時由於有些平臺不支持網頁跳轉登陸,因此咱們須要檢查用戶手機上面是否有安裝該平臺軟件來顯示頁面,大體效果以下圖:
圖片描述git

當時需求只有微信、朋友圈、短信三個分享,爲了趕進度,十分鐘寫完,當時的思路是:github

  1. 整個頁面是個UIView,點擊更多的時候進行初始化,而後add到window上面;微信

  2. 頁面最底下放置一個UIView來實現出現和隱藏的時候透明度在0-0.3之間漸變,添加點擊手勢響應Remove操做;佈局

  3. 下面的主要操做區域放置一個背景顏色爲rgb都是240的UIView,根據傳入的type計算總高度,中間放置一個顏色爲rgb都是224的UILabel作分割線,垂直方向動畫移入和移出頁面;學習

  4. 三個分享按鈕+舉報按鈕都使用UIButton,設置圖片和標題的EdgeInsets屬性爲UI所需樣式,舉報按鈕根據傳入的type控制;動畫

  5. 佈局頁面的時候判斷手機是否安裝有微信,沒有的話只顯示短信分享;ui

  6. 使用delegate與調用分享的Controller通訊;
    而後適配一下,這樣寫最直接,可是代碼量大,純代碼設置每一個按鈕的各項屬性,還要根據用戶是否安裝某些軟件來配置顯示的按鈕的座標,擴展性不強,按鈕很少還好,要是隨着業務發展加入更多的分享平臺,就很坑爹了。atom

固然有不少人使用的是UIActionSheet+UIScrollView實現,一樣的道理,這樣實現須要根據按鈕是否顯示來動態佈局頁面,需求變動就得從新佈局,代碼寫着不爽。
下面說說個人思路。spa

正題

前幾天羣裏有個哥們問我怎麼在UMeng的界面上面加個複製按鈕?顯然不太好弄,因而本着負責任的態度,結合我這一年來學到的知識,從新梳理了一遍整個需求:code

  1. 每組按鈕可能須要組頭來放置文字提示;

  2. 每一個分享的按鈕的圖文樣式須要方便隨時調節;

  3. 根據用戶手機是否安裝某些平臺來控制是否生成/顯示某些按鈕(全部按鈕的座標須要動態控制);

  4. 可能有兩行可能有一行,也可能有不少行(後期可能會有其餘需求);

  5. 一組按鈕數量過多時,可能須要一行橫向滑動顯示,也可能須要縱向多行排布;

  6. 須要有顯示和隱藏的動畫效果;

  7. 最底部可能須要有個取消或者"X"按鈕;

前面提到的幾種方法,一旦更改需求,好比橫向滑動改爲縱向排布,代碼寫起來就會很痛苦,仍是那句話,代碼寫起來要本身以爲爽才行,下面看看這些需求對應的解決方案:

  1. 組頭、組尾、可能單行也可能多行的需求,最底部有個取消按鈕,一個UITableView就能知足了,header、section、footer,根據dataSource能夠很是方便地控制顯示什麼和顯示與否;

  2. 按鈕樣式的調節和有可能橫向排布或縱向排布,使用UICollectionView能夠完美解決,UITableView的每一行裏面放置一個UICollectionView,UICollectionViewCell就是按鈕樣式,調節樣式改一個地方就行,排布方式setScrollDirection便可;

  3. 根據軟件的安裝狀態來動態控制顯示按鈕,用到這兩個控件,很顯然咱們只須要控制數據源就行了;
    因此數據源的結構應該是這樣的:

圖片描述

值得一提的思路

因爲目前在重構公司項目,因此文章結尾給出來的Demo中,分享按鈕事件沒有使用Delegate去操做Controller,而是採用的OC的runtime反射調用,根據方法名反過來構造SEL方法,而後判斷傳入actionVC是否響應該方法,響應就performSelector執行;
一樣的道理,其實model同樣能夠有個方法屬性,可是這樣寫的話構造數據源所在的類必須聲明實現該方法,而且須要引用model文件,本人的想法是簡化操做,不要寫太多沒有必要的代碼。
看看代碼:

對於Controller的引用

@property (nonatomic, weak) id actionVC;
A.使用Dictionary

1.構造數據源

NSMutableDictionary *wechatDic = [[NSMutableDictionary alloc]initWithDictionary:@{@"imageName":@"wechat_icon", @"title":@"微信", @"actionName":@"shareToWeChatAction"}];

2.Item點擊交互

NSDictionary *dic = _dataSource[indexPath.row];
    NSString *actionStr = dic[@"actionName"];
    SEL action = NSSelectorFromString(actionStr);
     
    if ([self.actionVC respondsToSelector:action]) {
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"//去除警告
        [self.actionVC performSelector:action withObject:nil];
    }
B.使用model(使用的地方須要引入頭文件和實現響應selector構造的方法)

1.構造數據源

M_Share *wechatModel = [[M_Share alloc]init];
        wechatModel.title = @"微信";
        wechatModel.imageName = @"wechat_icon";
        wechatModel.selector = @selector(shareToWeChatAction);//所在類須要聲明/實現該方法
        [sectionOne addObject:wechatModel];
    
        [_dataSource addObject:sectionOne];

2.Item點擊交互

M_Share *shareModel = _dataSource[indexPath.row];
    if ([self.actionVC respondsToSelector:shareModel.selector]) {
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"//去除警告
        [self.actionVC performSelector:shareModel.selector withObject:nil];
    }

值得一提的是,這裏從邏輯上來說沒有任何問題,可是系統始終會報一個警告,看了一下前輩們的解決辦法是加了一行代碼去除leaks警告:

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

因此順便了解一一下去除項目中沒必要要的警告的方法,好比方法的廢棄警告,找到項目Target中的Build Phases下的Compile Sources,將裏面想要過濾警告的item後面編輯寫入-w後保存該文件裏面的警告就過濾掉了。

最後

抽時間整理成Demo出來放到github上面了:UMengDiyShareDemo
感謝閱讀,但願本文對你有幫助!

本人座標杭州,後續我會陸續把工做中遇到的問題及解決方案分享出來,互相交流學習,本人QQ:815187811,歡迎結交[笑臉].

相關文章
相關標籤/搜索