iOS APP框架搭建簡(jiǎn)析(附GitHub托管Demo)

奮斗.png

都說(shuō)“三歲看老”,我在和諧社會(huì)中摸爬 打滾了也近三個(gè)年頭,這不快過(guò)年了,今年朋友/發(fā)小尋找“心理平衡”的首選對(duì)象依舊是哥,看著大家滿意而歸的身影,榮幸之至!捧一捧涼水撲到臉上,抬頭照照鏡子打量著依舊“枯瘦如柴”的自己,看著時(shí)間給刻下的“抬頭紋”,盯著那渾濁但依舊堅(jiān)定的眼睛,哥想對(duì)自己說(shuō):“大雁,你可以的,雖然沒(méi)有以前好配合了,你終有一天會(huì)成功的,雖然還很遙遠(yuǎn)!乖乖,好了,傻B可以寫帖子了......”

前言

不管開(kāi)發(fā)任何軟件,我們的原則就是盡量做到“高內(nèi)聚低耦合”。所謂“低耦合”是指軟件結(jié)構(gòu)中模塊與模塊之間的耦合度或關(guān)聯(lián)程度,模塊之間接口的調(diào)用及實(shí)現(xiàn)的復(fù)雜度、交互數(shù)據(jù)的多少等,決定了軟件耦合度的高低強(qiáng)弱;所謂“高內(nèi)聚”是從模塊內(nèi)部功能的層面而言的,模塊內(nèi)部特定功能的代碼元素的緊密程度決定了代碼內(nèi)聚性的高低。

網(wǎng)上不乏有所謂“十分鐘搭建強(qiáng)壯APP框架”、“快速搭建強(qiáng)壯APP框架”等帖子,且不去講好壞,總之,實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),今天我簡(jiǎn)單匯報(bào)下本人做項(xiàng)目時(shí),框架的搭建流程及注意事項(xiàng)。

框架搭建

框架搭建是個(gè)勞神費(fèi)心的事情,因?yàn)樵诖罱〞r(shí)你要考慮到各種可能,比如:怎么設(shè)計(jì)使得流程更清晰?怎么設(shè)計(jì)更易于分工協(xié)作?怎么設(shè)計(jì)更容易快速定位代碼模塊?怎么保證系統(tǒng)的易擴(kuò)展性?等等都是我們要提前把握好的。先看下大致效果圖如下:

啟動(dòng)圖效果.png

最終效果.gif

一、 框架結(jié)構(gòu)

APP的結(jié)構(gòu)一般分為三條線:

  • 一條主框架流程;
  • 一條是用戶登錄框架流程;
  • 一條其他如廣告頁(yè)、歡迎頁(yè)等

相對(duì)而言,主框架流程較為復(fù)雜,頂級(jí)容器為UITabBarController,子容器為UINavigationController,其中頂級(jí)容器放3-5個(gè)導(dǎo)航控制器,導(dǎo)航控制器的rootViewController為各模塊的首頁(yè)。登錄框架流程及其他一般為線性流程,個(gè)別會(huì)涉及到根視圖的切換,相對(duì)簡(jiǎn)單,如果畫成樹狀結(jié)構(gòu)圖的話大致如下:


APP結(jié)構(gòu)圖.png

二、 StoryBoard分離

為了配置三方庫(kù)方便,我使用CocoaPods工程(基于CocoaPods 1.1.1),下為Podfile文件引入的三方庫(kù):

platform :ios,’8.0’

target ‘EVNEstorePlatform’ do

pod 'MBProgressHUD', '~> 1.0.0'
pod 'FMDB'
pod 'SDWebImage', '~> 3.8'
pod 'IQKeyboardManager', '~> 3.3.7'
pod 'MJRefresh'
pod 'MJExtension'
pod 'MWPhotoBrowser'
pod 'AFNetworking', '~> 3.0'

end

如遇到問(wèn)題,可參照CocoaPods工作原理及使用中遇到的問(wèn)題,解決或問(wèn)阿度。

在實(shí)際的項(xiàng)目開(kāi)發(fā)中,沒(méi)有說(shuō)誰(shuí)的框架更優(yōu),結(jié)構(gòu)都是大同小異,適合自己的團(tuán)隊(duì)才是最重要的。單從框架搭建及界面布局而言,有的團(tuán)隊(duì)喜歡StoryBoard,因?yàn)樗?jiàn)即所得,給外行介紹起來(lái)較為方便,一個(gè)模塊的所有的界面鋪滿屏幕,很酷炫的感覺(jué)。有的團(tuán)隊(duì)喜歡純代碼,當(dāng)看到自己寫一串串字符渲染出“神秘”動(dòng)畫,說(shuō)不出的滿足感。當(dāng)然我們團(tuán)隊(duì)奉行的是中庸之道,框架搭建+個(gè)別簡(jiǎn)易界面我們使用StoryBoard,其他使用純代碼的方式,這也是踩過(guò)坑之后,倒逼的結(jié)果。


StoryBoard.png

毋庸置疑StoryBoard有很多的優(yōu)點(diǎn),但對(duì)于團(tuán)隊(duì)協(xié)作開(kāi)發(fā),有時(shí)會(huì)有說(shuō)不出的痛,比如:同時(shí)修改StoryBoard文件遇到的沖突;即便是細(xì)微的位移調(diào)整,編譯起來(lái)也需要足夠耐心;更新了下Xcode怎么布局全亂了等等問(wèn)題,正因?yàn)榇耍覀儾捎谜壑蟹桨福M量將StoryBoard分離使用,Main.storyboard中為主框架頂級(jí)容器和登錄流程的頂級(jí)容器,而其他3-5個(gè)模塊如,首頁(yè)Host.storyboard、個(gè)人中心MineCenter.storyboard等,使用單獨(dú)的StoryBoard文件,除此之外基本使用純代碼方式編寫。


模塊.png
MainStoryBoard.png
MineCenterStoryBoard.png

在進(jìn)行故事版分離時(shí),主要是自定義UITabBarController的過(guò)程。
首先,根據(jù)上面模板圖,新建故事版文件;
然后,按照第一節(jié)框架結(jié)構(gòu)圖,將特定的控制器容器、導(dǎo)航控制器、視圖控制器拖入對(duì)應(yīng)的故事版中(StoryBoard文件);
再次,在自定義的UITabBarController中,連接各個(gè)模塊,在這個(gè)過(guò)程中UITabBarController起到了應(yīng)用的連接中樞的作用,為了炫技,哥做了個(gè)中間凸起效果,主要的TabBarController代碼如下:

#pragma mark: 首頁(yè)storyboard
    UIImage *hostSelectImg = [UIImage imageNamed:@"hostViewSelect"];
    UIImage *hostUnSelectImg = [UIImage imageNamed:@"hostViewUnSelect"];
    UIStoryboard *hostSB = [UIStoryboard storyboardWithName:@"Host" bundle:nil];
    UINavigationController *hostNaviVC = [hostSB instantiateViewControllerWithIdentifier:@"hostNavigationC"];
    hostNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"首頁(yè)" image:[self scaleImage:hostUnSelectImg] selectedImage:[self scaleImage:hostSelectImg]];
    hostNaviVC.tabBarItem.tag = 0;

#pragma mark: 關(guān)注storyboard
    UIImage *attentionSelectImg = [UIImage imageNamed:@"attentionSelect.png"];
    UIImage *attentionUnSelectImg = [UIImage imageNamed:@"attentionUnSelect.png"];
    UIStoryboard *attentionSB = [UIStoryboard storyboardWithName:@"Attention" bundle:nil];
    UINavigationController *attentionNaviVC = [attentionSB instantiateViewControllerWithIdentifier:@"attentionNavigationC"];
    attentionNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"關(guān)注" image:[self scaleImage:attentionUnSelectImg] selectedImage:[self scaleImage:attentionSelectImg]];
    attentionNaviVC.tabBarItem.tag = 1;

#pragma mark: 發(fā)現(xiàn)storyboard
    UIImage *findSelectImg = [UIImage imageNamed:@"findSelect.png"];
    UIImage *findUnSelectImImg = [UIImage imageNamed:@"findUnSelect.png"];
    UIStoryboard *findSB = [UIStoryboard storyboardWithName:@"Find" bundle:nil];
    UINavigationController *findNaviVC = [findSB instantiateViewControllerWithIdentifier:@"findNavigationC"];
    findNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"發(fā)現(xiàn)" image:[UIImage imageWithCGImage:findUnSelectImImg.CGImage scale:1.5 orientation:findUnSelectImImg.imageOrientation] selectedImage:[UIImage imageWithCGImage:findSelectImg.CGImage scale:1.5 orientation:findSelectImg.imageOrientation]];
    [findNaviVC.tabBarItem setImageInsets:UIEdgeInsetsMake(-14, 0, 14, 0)];
    findNaviVC.tabBarItem.tag = 2;
    findNaviVC.tabBarItem.selectedImage = [[UIImage imageNamed:@"findSelect.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    findNaviVC.tabBarItem.image = [[UIImage imageNamed:@"findUnSelect.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

#pragma mark: 購(gòu)物車storyboard
    UIImage *goodsCarSelectImg = [UIImage imageNamed:@"goodsCarSelect.png"];
    UIImage *goodsCarUnSelectImg = [UIImage imageNamed:@"goodsCarUnSelect.png"];
    UIStoryboard *goodsCarSB = [UIStoryboard storyboardWithName:@"GoodsCar" bundle:nil];
    UINavigationController *goodsCarNaviVC = [goodsCarSB instantiateViewControllerWithIdentifier:@"goodsCarNavigationC"];
    goodsCarNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"購(gòu)物車" image:[self scaleImage:goodsCarUnSelectImg] selectedImage:[self scaleImage:goodsCarSelectImg]];
    goodsCarNaviVC.tabBarItem.tag = 3;

#pragma mark: 個(gè)人中心storyboard
    UIImage *mineCenterSelectImg = [UIImage imageNamed:@"mineCenterSelect.png"];
    UIImage *mineCenterUnSelectImg = [UIImage imageNamed:@"mineCenterUnSelect.png"];
    UIStoryboard *mineCenterSB = [UIStoryboard storyboardWithName:@"MineCenter" bundle:nil];
    UINavigationController *mineCenterNaviVC = [mineCenterSB instantiateViewControllerWithIdentifier:@"mineCenterNavigationC"];
    mineCenterNaviVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"我" image:[self scaleImage:mineCenterUnSelectImg] selectedImage:[self scaleImage:mineCenterSelectImg]];
    mineCenterNaviVC.tabBarItem.tag = 4;

#pragma mark: 連接
    self.viewControllers = @[hostNaviVC, attentionNaviVC, findNaviVC, goodsCarNaviVC, mineCenterNaviVC];

最后, 創(chuàng)建各模塊對(duì)應(yīng)的視圖控制器,將其匹配到StoryBoard中的控件中。

框架目錄.png

三、 APP使用流程

APP運(yùn)行的流程一般為,首先執(zhí)行AppDelegate的代理方法didFinishLaunching,進(jìn)入啟動(dòng)頁(yè),判斷是否是首次使用APP,如果是進(jìn)入歡迎頁(yè),否則直接驗(yàn)證廣告頁(yè)驗(yàn)證,進(jìn)而進(jìn)入加載廣告頁(yè),最后進(jìn)入首頁(yè)。具體流程圖如下:


APP流程圖.png

我的框架也是根據(jù)這個(gè)流程搭建。

結(jié)語(yǔ)

戰(zhàn)戰(zhàn)兢兢,如履薄冰,望再接再厲,下為工程托管地址,EVNEstorePlatform GitHub,如果覺(jué)得有幫助,請(qǐng)不要吝嗇點(diǎn)贊,可以在GitHub給個(gè)star,O(∩_∩)O謝謝......

本文已在版權(quán)印備案,如需轉(zhuǎn)載請(qǐng)?jiān)诎鏅?quán)印獲取授權(quán)。
獲取版權(quán)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容