项目总结:框架

一 整体布局:
     if(未授权){
          加载授权WabView(保存授权信息到本地沙盒) —>授权完成显示主页
        //沙盒路径
        NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
        NSString *path = [doc stringByAppendingPathComponent:@"account.archive"];
//        NSLog(@"%@",path);
        //将返回的账号数据 --> 模型再存到沙盒
        MCAccountModel *account =  [MCAccountModelaccountWithDic:responseObject];
        //要想把对象写进沙盒就要用到 NSKeyedArchiver 这个类不能在使用writeToFile的方法
        [NSKeyedArchiverarchiveRootObject:account toFile:path];
//        [responseObject writeToFile:path atomically:YES];

}else{
          if(根据沙盒路径下保存的新版本信息判断是否是新版本){
    NSString *key = @"CFBundleVersion";
   
//1.获取上一次的软件版本(沙盒中)
    NSString *lastVersion = [[NSUserDefaultsstandardUserDefaults] objectForKey:key];
    //2.获取当前版本(info.plist文件中)
    NSString *currentVersion = [NSBundlemainBundle].infoDictionary[key];
    UIWindow *window = [UIApplicationsharedApplication].keyWindow ;
    if ([currentVersion isEqualToString:lastVersion]) {
        window.rootViewController = tabBar;
    }else{
        window.rootViewController = [[NewFeatureViewControlleralloc]init];
       
//3.将新版本号存入沙盒
        [[
NSUserDefaultsstandardUserDefaults] setObject:currentVersion forKey:key];
        [[
NSUserDefaultsstandardUserDefaults]synchronize];
    }
               显示“新特性界面”(更新沙盒路径下保存的新版本)—>主页
          }else{
               直接显示主页
          }
}
在这里,保存到沙盒路径下的模型类需要说明一下,涉及到对象的归档和解档
#import "MCAccountModel.h"
@implementation MCAccountModel
+(instancetype)accountWithDic:(NSDictionary *)dic{
    MCAccountModel *account = [[selfalloc]init];
    account.access_token = [dic objectForKey:@"access_token"];
    account.expires_in = [dic objectForKey:@"expires_in"];
    account.uid = [dic objectForKey:@"uid"];
    return account;
}
/**
 * 
当一个对象要归档到沙盒中时要调用到这个方法 *
 * 
目的 : 在这个方法中说明对象的那些属性要存进沙盒
 */
-(void)encodeWithCoder:(NSCoder *)encoder{
    [encoder encodeObject : self . access_token forKey:@"access_token"];
    [encoder
encodeObject:self.expires_inforKey:@"expires_in"];
    [encoder encodeObject:self.uidforKey:@"uid"];
}
/**
 * 
当一个对象要从沙盒中解档时要调用到这个方法
 * 
目的 : 在这个方法中说明对象的那些属性要从沙盒中解档
 */
-(instancetype)initWithCoder:(NSCoder *)decoder{
    if ( self = [ super init]) {
       
self.access_token = [decoder decodeObjectForKey:@"access_token"];
       
self.expires_in = [decoder decodeObjectForKey:@"expires_in"];
        self.uid = [decoder decodeObjectForKey:@"uid"];
    }
   
return self;
}
@end
二 主框架 :

     主要的框架结构是 : 一个标签控制器下四个由导航控制器控制的ViewController,这里方法是将标签控制器子类化 MCBaseTabBarController
     
- ( void )viewDidLoad {
    [
super viewDidLoad];
   
//初始化子控制器
   
// 1.初始化子控制器
   
HomeViewController *home = [[HomeViewControlleralloc] init];
    [selfaddChildVc:home title:@"首页"image:@"tabbar_home"selectedImage:@"tabbar_home_selected"];
    MassageViewController *messageCenter = [[ MassageViewController alloc] init];
    [selfaddChildVc:messageCenter title:@"消息"image:@"tabbar_message_center"selectedImage:@"tabbar_message_center_selected"];
    DiscoverViewController *discover = [[ DiscoverViewController alloc] init];
    [selfaddChildVc:discover title:@"发现"image:@"tabbar_discover"selectedImage:@"tabbar_discover_selected"];
    MyinfoViewController *profile = [[ MyinfoViewController alloc] init];
    [selfaddChildVc:profile title:@""image:@"tabbar_profile"selectedImage:@"tabbar_profile_selected"];
    MCTabBar *tabBar = [[ MCTabBar alloc]init];
    tabBar. delegate = self ;
   
// 系统只读模式的属性 我们可以用KVC赋值
    [
selfsetValue:tabBar forKeyPath:@"tabBar"];
}
-( void )viewWillAppear:( BOOL )animated{
    [ super viewWillAppear:animated];
}
- (
void )addChildVc:( UIViewController *)childVc title:( NSString *)title image:( NSString *)image selectedImage:( NSString *)selectedImage
{
   
// 设置子控制器的文字
    childVc.title = title; // 同时设置 tabbar navigationBar 的文字
    // 设置子控制器的图片
    childVc.
tabBarItem . image = [ UIImage imageNamed:image];
    childVc.tabBarItem.selectedImage = [[UIImageimageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    // 设置文字的样式
   
NSMutableDictionary *textAttrs = [ NSMutableDictionary dictionary];
    textAttrs[
NSForegroundColorAttributeName] = MCColor(123, 123, 123);
   
NSMutableDictionary *selectTextAttrs = [NSMutableDictionarydictionary];
    selectTextAttrs[
NSForegroundColorAttributeName] = [UIColororangeColor];
    [childVc.
tabBarItemsetTitleTextAttributes:textAttrs forState:UIControlStateNormal];
    [childVc.tabBarItemsetTitleTextAttributes:selectTextAttrs forState:UIControlStateSelected];
    // 先给外面传进来的小控制器 包装一个导航控制器
   
MCBaseNavigationController *nav = [[MCBaseNavigationControlleralloc] initWithRootViewController:childVc];
   
// 添加为子控制器
    [
selfaddChildViewController:nav];
}
     在上面过程中标签控制器的tabBar 是根据需求自定义的样式

- ( instancetype )initWithFrame:( CGRect )frame
{
   
self = [ super initWithFrame:frame];
    if (self) {
        UIButton *plusBtn = [[ UIButton alloc]init];
        [plusBtn addTarget : self action:@selector(plusBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        [plusBtn setBackgroundImage :[ UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
        [plusBtn
setBackgroundImage:[UIImageimageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
        [plusBtn
setImage:[UIImageimageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
        [plusBtn setImage:[UIImageimageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
        plusBtn. size = plusBtn. currentBackgroundImage . size ;
        self . plusBtn = plusBtn;
        [ self addSubview:plusBtn];
    }
   
returnself;
}
通常需要重新布局系统控件时,都要复写这个方法来给系统的控件重新布局
-(void)layoutSubviews{
    [ super layoutSubviews];
    //1. 设置加号按钮的尺寸
   
self . plusBtn . centerX = self . width * 0.5 ;
    self.plusBtn.centerY = self.height * 0.5;
    //2. 设置其他控件的尺寸
   
CGFloat tabBarItemWith = self . width / 5 ;
   
int index = 0 ;
    for (UIView *view inself.subviews) {
        Class class = NSClassFromString ( @"UITabBarButton" );
        if ([view isKindOfClass :class]) {
            view.
width = tabBarItemWith;
            view.
x = tabBarItemWith * index;
            index ++;
            if (index == 2 ) {
                index ++;
            }
        }
    }   
}
三 模块共同属性和特点统一设置
     通常同一款应用不同的界面会有相似的属性,我们把这些属性统一设置在一个父类当中,也就是子类化一个公共的父类,这样就会减少很多代码量
比如:每个模块的导航栏左右两个按钮都是相同的,并且每个模块中pushi出来的视图的导航栏中的按钮也是相同的,并且每个模块pushi出来的VIewController的标签栏都是隐藏的,总结出这些共同属性接下来就着手在父类中去实现这些属性就可以了,当用到这些属性时只需要基于这个父类 ( MCBaseNavigationController)创建类就可以了
      UIBarButtonItem 在创建时(不管以什么方式创建)都会实现这个类方法,所以复写这个类方法,并添加共有属性
+ ( void )initialize
{
   
// 设置整个项目中的 item 主题样式
    UIBarButtonItem *item = [UIBarButtonItemappearance];
    // 设置普通状态
   
// key NS****AttributeName
    NSMutableDictionary *textAttrs = [NSMutableDictionarydictionary];
    textAttrs[ NSForegroundColorAttributeName ] = [ UIColor orangeColor];
    textAttrs[ NSFontAttributeName ] = [ UIFont systemFontOfSize:13];
    [item setTitleTextAttributes :textAttrs forState : UIControlStateNormal ];
    // 设置不可用状态
    NSMutableDictionary *disableTextAttrs = [NSMutableDictionarydictionary];
    disableTextAttrs[ NSForegroundColorAttributeName ] = [ UIColor colorWithRed:0.6green:0.6blue:0.6alpha:0.7];
    disableTextAttrs[ NSFontAttributeName ] = [ UIFont systemFontOfSize:13];
    [item setTitleTextAttributes :disableTextAttrs forState : UIControlStateDisabled ];
}
/**
 *   * 
重写这个方法的目的 : 能够拦截所有 Push 进来的控制器
 *  @param viewController
即将 push 进来的控制器
 */
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if ( self . viewControllers . count > 0 ) { // 这时 pushi 进来的控制器 viewController, 不是第一个自控制器 ( 不是跟控制器 )
       
/* 自动显示和隐藏 tabbar */
        viewController.hidesBottomBarWhenPushed = YES;
        /* 设置导航栏上面的内容 */
        // 设置左侧按钮
        viewController.navigationItem.leftBarButtonItem = [UIBarButtonItemitemWithTarget:selfaction:@selector(back) image:@"navigationbar_back"highImage:@"navigationbar_back_highlighted"];
        // 设置右侧按钮
        viewController.
navigationItem . rightBarButtonItem = [ UIBarButtonItem itemWithTarget:selfaction:@selector(more) image:@"navigationbar_more"highImage:@"navigationbar_more_highlighted"];
    }
    [superpushViewController:viewController animated:animated];
}
-(void)back{
    [ self popViewControllerAnimated:YES];
}
-(void)more{
    [ self popToRootViewControllerAnimated:YES];
}
四 控件的封装
     项目中某些模块的控件需要实现复杂的功能,并且整个项目中有多个模块用到该控件,那么就要实现控件的封装,比如:首页(Home)的标题点击实现下拉菜单的功能,上述tabBar的封装,发现(Search)的搜索框都可以单独封装使用。
     下拉菜单
#import "MCTitleMenuView.h"

@interface MCTitleMenuView ()
{
   
UIImageView *_menuView;
}
@end
@implementation MCTitleMenuView
+( instancetype )menu{
    return [[ self alloc]init];
}
-(void)showSelf:(UIButton*)btn{
    //1. 获取最上面的窗口
    UIWindow *window = [[UIApplicationsharedApplication].windowslastObject];
    //2. 添加自己到窗口
    [window addSubview:self];
    //3. 设置尺寸
    self.frame = window.bounds;
    self . backgroundColor = [ UIColor clearColor];
    self . userInteractionEnabled = YES ;
    _menuView = [[ UIImageView alloc]initWithFrame:CGRectMake(20, 80, 200, 300)];
    // 调节下拉菜单的位置
   
CGRect newRect = [btn convertRect :btn. bounds toView:nil];
    _menuView.centerX = btn.centerX;
    _menuView . y = newRect. origin . y + btn. height ;
    _menuView.userInteractionEnabled = YES;
    if ( _content ) {
       
self . content . frame = CGRectMake ( 15 , 25 , _menuView . width - 30 , _menuView . height - 40 );
        _content.layer.cornerRadius = 5;
        [ _menuView addSubview:_content];
    }
    _menuView . image = [ UIImage imageNamed:@"popover_background"];
    [ self addSubview:_menuView];
}
-( void )dismis{
    [ _menuView removeFromSuperview];
    [ self removeFromSuperview];
}
-(
void )setContent:( UIView *)content{
   
_content = content;
}
-(void)setShowButton:(UIButton *)showButton{
    _showButton = showButton;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    for ( UITouch *touch in touches) {
        if ( _content ) {
            if (touch.view !=  _content) {
                _showButton . selected = NO ;
                [
self dismis];
            }
        }
else{
           
if (touch.view !=  _menuView) {
                _showButton.selected = NO;
                [ self dismis];
            }
        }
    }
}
搜索框
#import "MCSearchTextField.h"

@implementation MCSearchTextField

- (
instancetype )initWithFrame:( CGRect )frame
{
   
self = [ super initWithFrame:frame];
   
if (self) {
        [
selfcreatSearchTextfield];
    }
   
returnself;
}
-(void)creatSearchTextfield{
    self . background = [ UIImage imageNamed:@"searchbar_textfield_background"];
   
self.backgroundColor = [UIColorwhiteColor];
   
self.placeholder = @"搜索内容";
   
self.layer.cornerRadius = 5;
   
self.layer.borderWidth = 1;
   
self.layer.borderColor = [UIColorlightGrayColor].CGColor;
   
UIImageView *imageView= [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"searchbar_textfield_search_icon"]];
    imageView.
width = 30;
    imageView.
height = 30;
    imageView.contentMode = UIViewContentModeCenter;
    self . leftView = imageView;
    self.leftViewMode = UITextFieldViewModeAlways;
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值