關(guān)于項(xiàng)目思路的思考

  • 項(xiàng)目結(jié)構(gòu)更加清晰贺归,方便以后調(diào)試bug

  • 怎么讓項(xiàng)目結(jié)構(gòu)更加清晰,誰(shuí)的事情誰(shuí)管理

  • 分析項(xiàng)目架構(gòu)

    • 方便處理多人開發(fā)
    • 讓更多的功能復(fù)用
    • 讓代碼的結(jié)構(gòu)更加清晰
  • 自定義類的思路

    • 當(dāng)系統(tǒng)的某些類不能滿足需求的時(shí)候,需要給系統(tǒng)的類添加某些功能驯用,但還要保持原有類的功能驼鞭,采用自定義類,繼承系統(tǒng)的類(自定義控件轨蛤,自定義模型)
    • 讓項(xiàng)目的結(jié)構(gòu)更加清晰蜜宪,誰(shuí)的事情誰(shuí)管理,采取自定義類祥山,以后這個(gè)類的問題圃验,可以馬上定位到這個(gè)類做的哪些方法(自定義控制器)
  • 復(fù)習(xí)程序的運(yùn)行

    • main -> UIApplicationMain
    • 創(chuàng)建UIApplication對(duì)象
    • 創(chuàng)建UIApplication對(duì)象的代理
    • 開啟主運(yùn)行循環(huán),保持程序一直運(yùn)行
    • 加載info.plist文件,判斷下是否指定main
  • 關(guān)于窗口的建立

    • 創(chuàng)建窗口
    • 創(chuàng)建窗口的根控制器
    • 添加子控制器
    • 讓窗口顯示
    • 代碼實(shí)現(xiàn) (去消info中Main)
// 1.創(chuàng)建窗口
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

    // 2.創(chuàng)建窗口的跟控制器
    // 創(chuàng)建tabBarVc
    UITabBarController *tabBarVc  = [[UITabBarController alloc] init];
    // 設(shè)置窗口的根控制器
    self.window.rootViewController = tabBarVc;

    // 添加子控制器
    UIViewController *vc = [[UIViewController alloc] init];

    vc.view.backgroundColor = [UIColor redColor];

    [tabBarVc addChildViewController:vc];

  ...

    // 3.讓窗口顯示
    [self.window makeKeyAndVisible];
  • 搭建主架構(gòu)(讓程序更清晰化)

    • 不同的頁(yè)面交給不同的控制器管理缝呕,并放在不同的文件夾中澳窑。
  • 結(jié)構(gòu)清晰化,誰(shuí)的控件誰(shuí)管理供常。

  • 自定義UITabBarController

    • 內(nèi)部添加子控制器 可以進(jìn)行自定義方法摊聋,來抽取相同代碼,簡(jiǎn)化程序
    • 自定義 子控制器栈暇,誰(shuí)的控件麻裁,誰(shuí)管理,方便管理子控制器- 關(guān)于主流框架 (UITabBarController 和 UINavigationController) 主要是上面一個(gè)條,下面一個(gè)條煎源。
    • 一般是在 UITabBarController上添加UINavigationController 這樣的話色迂, 在UINavigationController上push子控制器的話 (這樣的話上面的條可以叫給push進(jìn)去的子控制器進(jìn)行管理)
  • 注意, 每運(yùn)行一步手销,都都要看看所運(yùn)行的效果歇僧,滿不滿足自己的需求。

    • 此處由于美工的的圖片(tabBar的圖標(biāo)圖片锋拖,大于tabBar的寬度诈悍,所以沒有顯示出想要的效果)【tabBar的寬度44 < 圖片高度】
      所以需要自定義tabBar,因?yàn)橄到y(tǒng)的tabBar不滿足需求
  • 自定義TabBar兽埃,取代原有tabBar侥钳,并實(shí)現(xiàn)原有tabBar的功能
    • 有多少按鈕控件,控件的樣式有什么決定柄错。 (對(duì)于tabBar慕趴,它的樣式是有對(duì)應(yīng)控制器決定的,可以這么說鄙陡,對(duì)應(yīng)控制器冕房,將所設(shè)置的樣式素材,存放在 tabBarItem 屬性中 tabBarItem就是一個(gè)模型數(shù)據(jù)趁矾,tabBar從模型數(shù)據(jù)中讀取了素材耙册,再賦值到它對(duì)應(yīng)的位置上)
    • 所以底層實(shí)現(xiàn)我認(rèn)為是這么幾步。
      • 從外界讀取模型數(shù)據(jù)毫捣,有多少控制器详拙,應(yīng)該就有多少組模型數(shù)據(jù)。
      • 提取模型數(shù)據(jù)蔓同,并將其賦值給子控件button上饶辙。
      • 給子控件設(shè)置位置
      • 點(diǎn)擊按鈕,跳轉(zhuǎn)到對(duì)應(yīng)的控制器斑粱。
      • 當(dāng)然弃揽,還有一些細(xì)節(jié)需要處理,比如按鈕不需要高亮指示则北,只需要選中和正常兩種狀態(tài)矿微, (所以需要自定義按鈕,重寫- (void)setHighlighted:(BOOL)highlighted方法尚揣,為空即可涌矢,讓其在高亮?xí)r不做任何操作);按鈕默認(rèn)選中第一個(gè)快骗;選中一個(gè)那么前一個(gè)就要取消選中娜庇。
      • 具體代碼如下塔次。
// 由于不確定什么時(shí)候有數(shù)據(jù)加入,所以采用懶加載方式名秀,進(jìn)行items的加載俺叭,加載完成后才進(jìn)行按鈕的創(chuàng)建以及賦值操作,不需要在視圖 一創(chuàng)建的時(shí)候泰偿,就取創(chuàng)建按鈕, 節(jié)約功耗
- (void)setItems:(NSArray *)items
{
    _items = items;

    for (UITabBarItem *item in items) {

        // 從items中取出模型數(shù)據(jù)蜈垮,并將其賦值給對(duì)應(yīng)按鈕
        UIButton *btn = [LXLTabBarButton buttonWithType:UIButtonTypeCustom];


        // 設(shè)置內(nèi)容
        [btn setBackgroundImage:item.image forState:UIControlStateNormal];

        [btn setBackgroundImage:item.selectedImage forState:UIControlStateSelected];

        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];

        btn.tag = self.subviews.count;

        if (self.subviews.count == 0) {
            // 為了程序之處耗跛,沒有子控件的時(shí)候,按鈕就已經(jīng)點(diǎn)擊攒发。
            [self btnClick:btn];
        }

        [self addSubview:btn];
    }
}
// 進(jìn)行子控件的布局调塌, 根據(jù)子控件的個(gè)數(shù),遍歷對(duì)每個(gè)子控件進(jìn)行布局
- (void)layoutSubviews
{
    [super layoutSubviews];

    int count = (int)self.subviews.count;

    CGFloat btnW = self.bounds.size.width / count;
    CGFloat btnH = self.bounds.size.height;
    CGFloat btnY = 0;
    CGFloat btnX = 0;
    // 布局按鈕的位置
    for (int i = 0; i < count; i++) {
        UIButton *btn = self.subviews[i];

        btnX = i * btnW;

        btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
    }

}

// 監(jiān)聽點(diǎn)擊事件惠猿, 由于是逆向傳值羔砾,所以需要代理,來完成點(diǎn)擊事件處理偶妖,并且傳入?yún)?shù)(點(diǎn)擊的是哪個(gè)按鈕)tag 姜凄,來完成讓控制器的跳轉(zhuǎn)
- (void)btnClick:(UIButton *)btn
{
    _selBtn.selected = NO;
    btn.selected = YES;
    _selBtn = btn;

    // 通知代理點(diǎn)擊了哪個(gè)角標(biāo)的按鈕
    if ([_delegate respondsToSelector:@selector(tabBar:didClickBtn:)]) {
        [_delegate tabBar:self didClickBtn:btn.tag];
    }
}

  • 對(duì)于父控件,tabBarController
    • 創(chuàng)建自定義tabBar控件趾访,并將其作為子控件放置在态秧,原系統(tǒng)tabBar之上,蓋住系統(tǒng)tabBar扼鞋。(需要注意的是申鱼,要移除系統(tǒng)原有的tabBar,但是系統(tǒng)底部處理的時(shí)候并不是馬上移除云头,會(huì)在過一段事件才進(jìn)行移除操作)捐友。
    • 需要將對(duì)應(yīng)的模型數(shù)組數(shù)據(jù)(懶加載),傳入溃槐,屬于順傳
    • 作為代理匣砖,完成對(duì)應(yīng)的方法,進(jìn)行控制器的跳轉(zhuǎn)
    • 具體代碼如下
// 取得模型數(shù)據(jù)昏滴,并存放在模型數(shù)組中
- (void)setUpOneChildViewController:(UIViewController *)vc image:(UIImage *)image selImage:(UIImage *)selImage
{

    // 設(shè)置tabBarButton的圖片脆粥,tabBarButton的內(nèi)容由對(duì)應(yīng)的子控制器的tabBarItem
    vc.tabBarItem.image = image;
    vc.tabBarItem.selectedImage = selImage;

    // 保存對(duì)應(yīng)子控制器的UITabBarItem
    [self.items addObject:vc.tabBarItem];

    [self addChildViewController:vc];
}

- (void)setUpTabBar
{
    // 1.移除系統(tǒng)的tabBar,移除系統(tǒng)自帶的tabBarButton
    [self.tabBar removeFromSuperview];
    NSLog(@"%@",self.tabBar);

    // 2.添加自己的tabBar
    LXLTabBar *tabBar = [[LXLTabBar alloc] init];

    tabBar.delegate = self;

    // tabBar按鈕的個(gè)數(shù),由tabBar子控制器個(gè)數(shù)決定
//    tabBar.count = (int)self.childViewControllers.count;
    // 傳對(duì)應(yīng)子控制器的tabBarItem數(shù)組
    tabBar.items = self.items;

    tabBar.backgroundColor = [UIColor greenColor];

    tabBar.frame = self.tabBar.frame;

    [self.view addSubview:tabBar];

}

// 遵守協(xié)議實(shí)現(xiàn)代理方法影涉,進(jìn)行界面的跳轉(zhuǎn)变隔。
#pragma mark  -LXLTabBarDelgate方法
// 當(dāng)點(diǎn)擊tabBar上的條的時(shí)候調(diào)用
- (void)tabBar:(XMGTabBar *)tabBar didClickBtn:(NSInteger)index
{
    // 切換界面
    self.selectedIndex = index;
}
  • 對(duì)于跳轉(zhuǎn)按鈕的添加
    • 我覺得有兩種方案
      • 添加到最后一個(gè)cell上去
      • 直接添加到collectionView上去。
    • 第一種方案的實(shí)現(xiàn)
// 判斷是否是最后一個(gè)cell,可以根據(jù)indexPath進(jìn)行判斷
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

  ...

    // 給最后一個(gè)cell添加一個(gè)立即體驗(yàn)按鈕
    // 告訴cell是否是最后一個(gè)
    // 宏定義數(shù)目為4
    [cell setIndexPath:indexPath count:LXLPage];
//    [cell setIndexPath:indexPath count:4]
//    if (indexPath.item == XMGPage - 1) {
//        // 添加立即體驗(yàn)按鈕
//
//    }

    return cell;
}
  • cell內(nèi)部拿到indexPathcount進(jìn)行判斷
// 用來判斷下當(dāng)前cell對(duì)象是否是最后一個(gè)cell
- (void)setIndexPath:(NSIndexPath *)indexPath count:(int)count
{
    if (indexPath.item == count - 1) {
        // 最后一個(gè)cell
        // 添加一個(gè)立即體驗(yàn)按鈕,首先保存整個(gè)cell只有一個(gè)體驗(yàn)按鈕

        // 顯示這個(gè)按鈕
        self.startBtn.hidden = NO;

    }else{ // 不是最后一個(gè)cell

        // 隱藏這個(gè)按鈕,涉及到循環(huán)引用蟹倾,否則就會(huì)被別的cell所引用匣缘。
        self.startBtn.hidden = YES;
    }
}

  • 由于cell的按鈕是用的時(shí)候才進(jìn)行顯示猖闪,(所以可以進(jìn)行懶加載
- (UIButton *)startBtn
{
    if (_startBtn == nil) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        _startBtn= btn;

        [btn setBackgroundImage:[UIImage imageNamed:@"guideStart"] forState:UIControlStateNormal];

        // 尺寸可以進(jìn)行自適應(yīng)'自己根據(jù)圖片來安排大小'
        [btn sizeToFit];
        // 位置確定
        btn.center = CGPointMake(self.width * 0.5 , self.height * 0.9);
        [self.contentView addSubview:btn];
    }

    return _startBtn;
}

  • 對(duì)于控制器之間的跳轉(zhuǎn),點(diǎn)擊按鈕跳轉(zhuǎn)到新控制器肌厨。
    • 沒有任何聯(lián)系的控制器跳轉(zhuǎn)培慌,直接跳轉(zhuǎn)即可。 創(chuàng)建到主窗口根控制器顯示柑爸,代替原有主窗口根控制器
// 點(diǎn)擊立即體驗(yàn)按鈕的時(shí)候調(diào)用
- (void)start
{
    // 跳轉(zhuǎn)到主框架界面吵护。界面之間跳轉(zhuǎn),導(dǎo)航控制器表鳍,tabBarVc,modal

    // 不能使用modal原因:新特性界面一直存在馅而,被窗口的根控制器一直強(qiáng)引用

    LXLTabBarController *vc = [[LXLTabBarController alloc] init];

    // 設(shè)置窗口的根控制器為主框架控制器
   [UIApplication shareApplication].keyWindow.rootViewController = vc;
}

  • 第二種方法(代碼實(shí)現(xiàn))
- (viod)viewDidLoad{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setImage:[UIImage imageNamed:@"guideStart"] forState:UIControlStateNormal];
    [btn sizeToFit];
    // 初始化位置直接設(shè)置在 最終位置,而且只創(chuàng)建一次譬圣,不必思考情況
    btn.center = CGPointMake(self.collectionView.width * (LXLPageCount - 0.5), self.collectionView.height * 0.9);
    [self.collectionView addSubview:btn];
    [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
}
// 跳轉(zhuǎn)控制器
- (void)btnClick
{
     LXLTabBarController *vc =[[LXLTabBarController alloc]init];

    [UIApplication sharedApplication].keyWindow.rootViewController =vc;
}

  • 總結(jié)一下瓮恭,我覺得第二個(gè)方法好,因?yàn)槭强刂破鬟M(jìn)行跳轉(zhuǎn)厘熟,我覺得完全是控制器自己的事屯蹦,交給它完全是可以處理的。如果交給cell的話绳姨,還需要額外的設(shè)置登澜,以及判斷清空。從代碼量來看飘庄,還是直接設(shè)置好一點(diǎn)帖渠。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市竭宰,隨后出現(xiàn)的幾起案子空郊,更是在濱河造成了極大的恐慌,老刑警劉巖切揭,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狞甚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡廓旬,警方通過查閱死者的電腦和手機(jī)哼审,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孕豹,“玉大人涩盾,你說我怎么就攤上這事±常” “怎么了春霍?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)叶眉。 經(jīng)常有香客問我址儒,道長(zhǎng)芹枷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任莲趣,我火速辦了婚禮鸳慈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喧伞。我一直安慰自己走芋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布潘鲫。 她就那樣靜靜地躺著翁逞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪次舌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天兽愤,我揣著相機(jī)與錄音彼念,去河邊找鬼。 笑死浅萧,一個(gè)胖子當(dāng)著我的面吹牛逐沙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洼畅,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吩案,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了帝簇?” 一聲冷哼從身側(cè)響起徘郭,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丧肴,沒想到半個(gè)月后残揉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芋浮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年抱环,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纸巷。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镇草,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘤旨,到底是詐尸還是另有隱情梯啤,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布存哲,位于F島的核電站条辟,受9級(jí)特大地震影響黔夭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜羽嫡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一本姥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杭棵,春花似錦婚惫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至滓侍,卻和暖如春蒋川,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撩笆。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工捺球, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夕冲。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓氮兵,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親歹鱼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子泣栈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,111評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件弥姻、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,102評(píng)論 4 62
  • 1南片、什么是RunLoop?2庭敦、開發(fā)中如何使用RunLoop?什么應(yīng)用場(chǎng)景铃绒?3、RunLoop和線程有什么關(guān)系螺捐?4颠悬、...
    Mr吳標(biāo)閱讀 2,003評(píng)論 2 0
  • 昨晚我做了個(gè)夢(mèng)赔癌,夢(mèng)里我被夢(mèng)想追殺了,是的你沒聽錯(cuò)澜沟,他的名字是叫夢(mèng)想灾票。夢(mèng)境的開始我并不知道他是誰(shuí),我只知道有人在追殺...
    草塘不會(huì)游泳閱讀 352評(píng)論 0 0