iOS必會(huì)—十分鐘學(xué)會(huì)搭建微信和微博兩種主流框架(純代碼)

目錄:

  • 1、兩種框架的介紹
  • 2、微信主流框架的實(shí)現(xiàn)思路
  • 3、微信主流框架的代碼實(shí)現(xiàn)
  • 4、微博主流框架的實(shí)現(xiàn)思路
  • 5、微博主流框架的代碼實(shí)現(xiàn)
  • 6、總結(jié)
  • 7、Demo下載

介紹

實(shí)際開(kāi)發(fā)中,我們常會(huì)見(jiàn)到兩種主流框架,一種類(lèi)似于微信,UIWindow的根rootViewControllerUITabBarController,然后調(diào)用addChildViewController(繼承自UIViewController)添加子控制器。然后實(shí)現(xiàn)控制器的跳轉(zhuǎn)。

簡(jiǎn)述下點(diǎn)擊UITabBarController的UITabBar切換控制器的原理:

點(diǎn)擊UITabBarController上的UITabBar跳轉(zhuǎn)控制器的原理是:
很多人未曾注意到UIViewController有個(gè)容器屬性,可以添加一組子控制器。
@property(nonatomic,readonly) NSArray<__kindof UIViewController *> *childViewControllers NS_AVAILABLE_IOS(5_0);
當(dāng)然也可以通過(guò)如下方法添加子控制器
- (void)addChildViewController:(UIViewController *)childController NS_AVAILABLE_IOS(5_0);

UITabBarController繼承自UIViewController,當(dāng)然也會(huì)繼承這個(gè)屬性和方法。
UITabBarController的代理協(xié)議UITabBarControllerDelegate中有- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;這個(gè)方法,點(diǎn)擊UITabBar時(shí),會(huì)將數(shù)組中的對(duì)應(yīng)的UIViewController取出放在當(dāng)前界面并顯示。
當(dāng)點(diǎn)擊UITabBarController上的UITabBar時(shí),會(huì)實(shí)現(xiàn)這個(gè)代理方法并完成控制器的切換。

一、微信主流框架的搭建

1、微信主流框架的實(shí)現(xiàn)思路

微信的UITabBarController和系統(tǒng)的樣式相同,實(shí)現(xiàn)原理也一樣,所以在此主要講解下控制器之間代碼的實(shí)現(xiàn)思路和封裝。

  • 1.在A(yíng)ppDelegate中,將window的rootViewController設(shè)置為帶有UITabBarController的導(dǎo)航控制器;
  • 2.創(chuàng)建子控制器,設(shè)置子控制器的title,image,selectedImage等屬性
  • 3.設(shè)置子控制器的導(dǎo)航控制器,并添加到childViewController中

2、微信主流框架的代碼實(shí)現(xiàn)

1. 在A(yíng)ppDelegate中,將window的rootViewController設(shè)置為帶有UITabBarController的導(dǎo)航控制器;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 //類(lèi)似微信的UITabBarController
 GBWeChatTabBarController *weChatVc = [[GBWeChatTabBarController alloc]init];
    UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:weChatVc];
    self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    return YES;
}

2. 創(chuàng)建子控制器,設(shè)置子控制器的title,image,selectedImage等屬性

/**
 *  初始化一個(gè)子控制器
 *
 *  @param childVc           需要初始化的子控制器
 *  @param title             標(biāo)題
 *  @param imageName         圖標(biāo)
 *  @param selectedImageName 選中的圖標(biāo)
 */
- (void)addChildViewController:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName
{
    // 1.設(shè)置控制器的屬性
    childVc.title = title;
    // 設(shè)置圖標(biāo)
    childVc.tabBarItem.image = [UIImage imageNamed:imageName];
    // 設(shè)置選中的圖標(biāo)
    childVc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImageName];
    // 2.包裝一個(gè)導(dǎo)航控制器
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:childVc];
    [self addChildViewController:nav];
}

3. 設(shè)置子控制器的導(dǎo)航控制器,并添加到childViewController中


// 初始化所有的子控制器
- (void)setupAllChildViewControllers {
    // 1.ONE
    GBOneTableViewController *one = [[GBOneTableViewController alloc] init];
    [self addChildViewController:one  title:@"ONE" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"];
    
    // 2.TWO
    GBTwoTableViewController *two = [[GBTwoTableViewController alloc] init];
    [self addChildViewController:two title:@"TWO" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"];
    
    // 3.THREE
    GBThreeTableViewController *three = [[GBThreeTableViewController alloc] init];
    [self addChildViewController:three title:@"THREE" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"];
    
    // 4.FOUR
    GBFourTableViewController *four = [[GBFourTableViewController alloc] init];
    [self addChildViewController:four title:@"FOUR" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected"];
}

二、微博主流框架的搭建

但是微博就不同了。
回想一下,微信的UITabBarController切換是調(diào)用了代理方法,取出數(shù)組中對(duì)應(yīng)的控制器,然后顯示。
但點(diǎn)擊微博的中間的加號(hào)按鈕,彈出pop動(dòng)畫(huà)的界面,而不是子控制器。
那怎么實(shí)現(xiàn)這個(gè)功能呢?
嚴(yán)格來(lái)說(shuō),有UITabBarController有n個(gè)子控制器,下面的UITabBar就有n個(gè)UITabBarItem。但我們只有4個(gè)控制器,下面卻有5個(gè)UITabBarItem怎么辦?
顯然系統(tǒng)的UITabBar不好用,那就只能重寫(xiě)了。
所以我們自定義一個(gè)UITabBar類(lèi)的新類(lèi)GBTabBar。
由于UITabBar繼承自UIView,所以我們只要把中間的加號(hào)按鈕定義為一個(gè)button,然后通過(guò)在GBTabBar中[self addSubview:button]就可以了。
然后實(shí)現(xiàn)按鈕的點(diǎn)擊事件,并通過(guò)代理(或者block等方式)將點(diǎn)擊方法傳到UITabBarController中。
但注意,由于系統(tǒng)的UITabBarItem的會(huì)平分整個(gè)UITabBar,所以添加完button之后,我們需要重寫(xiě)每一個(gè)UITabBarItem的尺寸。

1、微博主流框架的實(shí)現(xiàn)思路

微信的UITabBarController和系統(tǒng)的樣式相同,實(shí)現(xiàn)原理也一樣,所以在此主要講解下控制器之間代碼的實(shí)現(xiàn)思路和封裝。

  • 1.在A(yíng)ppDelegate中,將window的rootViewController設(shè)置為帶有UITabBarController的導(dǎo)航控制器;
  • 2.創(chuàng)建子控制器,設(shè)置子控制器的title,image,selectedImage等屬性
  • 3.設(shè)置子控制器的導(dǎo)航控制器,并添加到childViewController中
  • 4.自定義新的UITabBar,然后在UITabBar上添加中間的加號(hào)按鈕
  • 5.重寫(xiě)layoutSubviews,完成布局。
  • 6.實(shí)現(xiàn)點(diǎn)擊事件,并定義代理方法,將代理方法傳至UITabBarController中

2、微博主流框架的代碼實(shí)現(xiàn)

1. 在A(yíng)ppDelegate中,將window的rootViewController設(shè)置為帶有UITabBarController的導(dǎo)航控制器;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 //類(lèi)似微信的UITabBarController
 GBWeiboTabBarViewController *weiboVc = [[GBWeiboTabBarViewController alloc]init];
    UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:weiboVc];
    self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    return YES;
}

2. 創(chuàng)建子控制器,設(shè)置子控制器的title,image,selectedImage等屬性

/**
 *  初始化一個(gè)子控制器
 *
 *  @param childVc           需要初始化的子控制器
 *  @param title             標(biāo)題
 *  @param imageName         圖標(biāo)
 *  @param selectedImageName 選中的圖標(biāo)
 */
- (void)addChildViewController:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName
{
    // 1.設(shè)置控制器的屬性
    childVc.title = title;
    // 設(shè)置圖標(biāo)
    childVc.tabBarItem.image = [UIImage imageNamed:imageName];
    // 設(shè)置選中的圖標(biāo)
    childVc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImageName];
    // 2.包裝一個(gè)導(dǎo)航控制器
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:childVc];
    [self addChildViewController:nav];
}

3. 設(shè)置子控制器的導(dǎo)航控制器,并添加到childViewController中

// 初始化所有的子控制器
- (void)setupAllChildViewControllers {
    // 1.ONE
    GBOneTableViewController *one = [[GBOneTableViewController alloc] init];
    [self addChildViewController:one  title:@"ONE" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"];
    
    // 2.TWO
    GBTwoTableViewController *two = [[GBTwoTableViewController alloc] init];
    [self addChildViewController:two title:@"TWO" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"];
    
    // 3.THREE
    GBThreeTableViewController *three = [[GBThreeTableViewController alloc] init];
    [self addChildViewController:three title:@"THREE" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"];
    
    // 4.FOUR
    GBFourTableViewController *four = [[GBFourTableViewController alloc] init];
    [self addChildViewController:four title:@"FOUR" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected"];
}

4. 自定義新的UITabBar,然后在UITabBar上添加中間的加號(hào)按鈕,并重寫(xiě)layoutSubviews,完成布局

#import "GBTabBar.h"

@interface GBTabBar ()

@property(nonatomic,strong) UIButton *customButton; //自定義加號(hào)按鈕

@end

@implementation GBTabBar

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame: frame];

    if (self) {
        // 添加一個(gè)加號(hào)按鈕
        UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [customButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
        [customButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
        [customButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
        [customButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
        customButton.bounds = CGRectMake(0, 0, customButton.currentBackgroundImage.size.width, customButton.currentBackgroundImage.size.height);
        //添加方法
        [customButton addTarget:self action:@selector(customButtonClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:customButton];
        self.customButton = customButton;
    }
    return self;
}

#pragma mark - system method
- (void)layoutSubviews {
    [super layoutSubviews];
    
    //先設(shè)置中間按鈕的位置
    self.customButton.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
    
    //計(jì)算每個(gè)按鈕的寬度
    CGFloat tabBarButtonW = self.frame.size.width / 5;
    CGFloat tabBarButtonIndex = 0;
    for (UIView *child in self.subviews) {
        Class class = NSClassFromString(@"UITabBarButton");
        if ([child isKindOfClass:class]) {
            child.frame = CGRectMake(tabBarButtonIndex * tabBarButtonW, 0, tabBarButtonW, self.frame.size.height);
            
            tabBarButtonIndex++;
            if (tabBarButtonIndex == 2) {
                tabBarButtonIndex++;
                }
        }
    }
}

5. 實(shí)現(xiàn)點(diǎn)擊事件,并定義代理方法,將代理方法傳至UITabBarController中

//  GBTabBar.h文件中

#import <UIKit/UIKit.h>

//custom delegate
@class GBTabBar;
@protocol GBTabBarDelegate <NSObject>

@optional
- (void)tabBarDidClickPlusButton:(GBTabBar *)tabBar;
@end

@interface GBTabBar : UITabBar
//此處代理名字不能為delegate,因?yàn)闀?huì)和UITabbar本身的delegate沖突
@property (nonatomic, weak) id<GBTabBarDelegate> myDelegate;
@end

//  GBTabBar.m文件中

#pragma mark - custom method
- (void)customButtonClick {
    NSLog(@"click");
    //遵守代理
    if ([self.myDelegate respondsToSelector:@selector(tabBarDidClickPlusButton:)]) {
        [self.myDelegate tabBarDidClickPlusButton:self];
    }
}

文末總結(jié):
在我認(rèn)為,寫(xiě)技術(shù)博客,兩種方式會(huì)尤low:

  • 從不結(jié)合實(shí)際需求,全篇大段的copy概念性知識(shí)點(diǎn),不講自己的理解的很low;
  • 大段的copy代碼,只做代碼表層級(jí)別的注釋說(shuō)明,不講解實(shí)現(xiàn)原理和思路的更low;

以上兩種技術(shù)博客極少需要?jiǎng)幽X,寫(xiě)作成本很低。
因?yàn)檎迟N大段純概念知識(shí)點(diǎn),不建立在實(shí)際使用場(chǎng)景下很難形象理解,加深記憶;
大篇幅粘貼純代碼可以說(shuō)純了碰到實(shí)際需求,解決淺層問(wèn)題,讀者看了很難舉一反三;
當(dāng)然,也并非說(shuō)無(wú)用,只是說(shuō)用處不大,見(jiàn)效甚微而且只是無(wú)根。
所以我把這類(lèi)博客歸結(jié)為無(wú)根知識(shí)。
所以也希望讀者在看作者的文章時(shí),多帶思考。很多知識(shí)點(diǎn)是代入式的講解,希望能幫你構(gòu)建自己的知識(shí)網(wǎng)羅。
我不做無(wú)根的作者,你也不要做淺層的讀者。

如有錯(cuò)誤歡迎指出,文畢,程序員注定不能做一個(gè)孤獨(dú)的勇士,也歡迎大家加微信號(hào)bin5211bin學(xué)習(xí)交流。

點(diǎn)擊下載Demo:
Demo下載

  • 代碼說(shuō)明,默認(rèn)是微博類(lèi)型框架,切換微信控制器只需要在A(yíng)ppDelegate中將navagationController的rootViewController改為weChatVc即可。
最后編輯于
?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,835評(píng)論 4 61
  • 前言的前言 唐巧前輩在微信公眾號(hào)「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各項(xiàng)指標(biāo)...
    VincentHK閱讀 5,581評(píng)論 3 44
  • 好一個(gè)春天,到處是花紅柳綠。春天到處都洋溢著生機(jī),看那早晨的露珠兒在荷葉上輕輕地滑過(guò),春風(fēng)吹綠了大地,神州大地好一...
    向春光原創(chuàng)文學(xué)閱讀 345評(píng)論 0 2
  • 我可以不解釋我的信仰 可以不思索我的夢(mèng)想 不喜歡劃定的路 不喜歡旁人的目光 我做著我喜歡的事 我不懂你怎么想 我就...
    愛(ài)貓的旅行狗閱讀 531評(píng)論 0 0
  • 我的微商之路,在我們那算是比較早的一批了 還記得,那是2015年的一個(gè)炎熱的夏天,那時(shí)候還不懂微商,只知道在微信慢...
    雙兒朵嘉濃護(hù)膚老師閱讀 411評(píng)論 0 0

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