一 整体布局:
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.获取上一次的软件版本(沙盒中)
//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];
//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_tokenforKey:@"access_token"];
[encoder encodeObject:self.expires_inforKey:@"expires_in"];
[encoder encodeObject:self.expires_inforKey:@"expires_in"];
[encoder
encodeObject:self.uidforKey:@"uid"];
}
/**
* 当一个对象要从沙盒中解档时要调用到这个方法
* 目的:在这个方法中说明对象的那些属性要从沙盒中解档
*/
/**
* 当一个对象要从沙盒中解档时要调用到这个方法
* 目的:在这个方法中说明对象的那些属性要从沙盒中解档
*/
-(instancetype)initWithCoder:(NSCoder
*)decoder{
if (self
= [superinit]) {
self.access_token = [decoder decodeObjectForKey:@"access_token"];
self.expires_in = [decoder decodeObjectForKey:@"expires_in"];
self.access_token = [decoder decodeObjectForKey:@"access_token"];
self.expires_in = [decoder decodeObjectForKey:@"expires_in"];
self.uid = [decoder
decodeObjectForKey:@"uid"];
}
returnself;
}
returnself;
}
@end
二 主框架 :
主要的框架结构是 : 一个标签控制器下四个由导航控制器控制的ViewController,这里方法是将标签控制器子类化MCBaseTabBarController
- (void)viewDidLoad
{
[superviewDidLoad];
//初始化子控制器
// 1.初始化子控制器
HomeViewController *home = [[HomeViewControlleralloc] init];
[superviewDidLoad];
//初始化子控制器
// 1.初始化子控制器
HomeViewController *home = [[HomeViewControlleralloc] init];
[selfaddChildVc:home
title:@"首页"image:@"tabbar_home"selectedImage:@"tabbar_home_selected"];
MassageViewController *messageCenter = [[MassageViewControlleralloc]
init];
[selfaddChildVc:messageCenter
title:@"消息"image:@"tabbar_message_center"selectedImage:@"tabbar_message_center_selected"];
DiscoverViewController *discover = [[DiscoverViewControlleralloc]
init];
[selfaddChildVc:discover
title:@"发现"image:@"tabbar_discover"selectedImage:@"tabbar_discover_selected"];
MyinfoViewController *profile = [[MyinfoViewControlleralloc]
init];
[selfaddChildVc:profile
title:@"我"image:@"tabbar_profile"selectedImage:@"tabbar_profile_selected"];
MCTabBar *tabBar = [[MCTabBaralloc]init];
tabBar.delegate
= self;
//系统只读模式的属性我们可以用KVC赋值
[selfsetValue:tabBar forKeyPath:@"tabBar"];
//系统只读模式的属性我们可以用KVC赋值
[selfsetValue:tabBar forKeyPath:@"tabBar"];
}
-(void)viewWillAppear:(BOOL)animated{
[superviewWillAppear:animated];
}
- (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
// 设置子控制器的文字
- (void)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
// 设置子控制器的文字
childVc.title = title;
// 同时设置tabbar和navigationBar的文字
//
设置子控制器的图片
childVc.tabBarItem.image = [UIImageimageNamed:image];
childVc.tabBarItem.image = [UIImageimageNamed:image];
childVc.tabBarItem.selectedImage
= [[UIImageimageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
//
设置文字的样式
NSMutableDictionary *textAttrs = [NSMutableDictionarydictionary];
textAttrs[NSForegroundColorAttributeName] = MCColor(123, 123, 123);
NSMutableDictionary *selectTextAttrs = [NSMutableDictionarydictionary];
selectTextAttrs[NSForegroundColorAttributeName] = [UIColororangeColor];
[childVc.tabBarItemsetTitleTextAttributes:textAttrs forState:UIControlStateNormal];
NSMutableDictionary *textAttrs = [NSMutableDictionarydictionary];
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];
MCBaseNavigationController *nav = [[MCBaseNavigationControlleralloc] initWithRootViewController:childVc];
// 添加为子控制器
[selfaddChildViewController:nav];
}
在上面过程中标签控制器的tabBar 是根据需求自定义的样式
- (instancetype)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
{
self = [superinitWithFrame:frame];
if (self) {
UIButton *plusBtn = [[UIButtonalloc]init];
[plusBtn
addTarget:selfaction:@selector(plusBtnClick:)
forControlEvents:UIControlEventTouchUpInside];
[plusBtn
setBackgroundImage:[UIImageimageNamed:@"tabbar_compose_button"]
forState:UIControlStateNormal];
[plusBtn setBackgroundImage:[UIImageimageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
[plusBtn setImage:[UIImageimageNamed:@"tabbar_compose_icon_add"] 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;
[selfaddSubview:plusBtn];
}
returnself;
}
returnself;
}
通常需要重新布局系统控件时,都要复写这个方法来给系统的控件重新布局
-(void)layoutSubviews{
[superlayoutSubviews];
//1.设置加号按钮的尺寸
self.plusBtn.centerX = self.width * 0.5;
self.plusBtn.centerX = self.width * 0.5;
self.plusBtn.centerY
= self.height *
0.5;
//2.设置其他控件的尺寸
CGFloat tabBarItemWith = self.width/5;
int index = 0;
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;
view.width = tabBarItemWith;
view.x = tabBarItemWith * index;
index ++;
if (index ==
2) {
index ++;
}
}
}
index ++;
}
}
}
}
三 模块共同属性和特点统一设置
通常同一款应用不同的界面会有相似的属性,我们把这些属性统一设置在一个父类当中,也就是子类化一个公共的父类,这样就会减少很多代码量
比如:每个模块的导航栏左右两个按钮都是相同的,并且每个模块中pushi出来的视图的导航栏中的按钮也是相同的,并且每个模块pushi出来的VIewController的标签栏都是隐藏的,总结出这些共同属性接下来就着手在父类中去实现这些属性就可以了,当用到这些属性时只需要基于这个父类 (MCBaseNavigationController)创建类就可以了
UIBarButtonItem 在创建时(不管以什么方式创建)都会实现这个类方法,所以复写这个类方法,并添加共有属性
+ (void)initialize
{
//设置整个项目中的item主题样式
{
//设置整个项目中的item主题样式
UIBarButtonItem *item = [UIBarButtonItemappearance];
//设置普通状态
// key:NS****AttributeName
// key:NS****AttributeName
NSMutableDictionary *textAttrs = [NSMutableDictionarydictionary];
textAttrs[NSForegroundColorAttributeName]
= [UIColororangeColor];
textAttrs[NSFontAttributeName]
= [UIFontsystemFontOfSize:13];
[item
setTitleTextAttributes:textAttrs
forState:UIControlStateNormal];
//设置不可用状态
NSMutableDictionary *disableTextAttrs = [NSMutableDictionarydictionary];
disableTextAttrs[NSForegroundColorAttributeName]
= [UIColorcolorWithRed:0.6green:0.6blue:0.6alpha:0.7];
disableTextAttrs[NSFontAttributeName]
= [UIFontsystemFontOfSize:13];
[item
setTitleTextAttributes:disableTextAttrs
forState:UIControlStateDisabled];
}
/**
* * 重写这个方法的目的:能够拦截所有Push进来的控制器
* @param viewController 即将push进来的控制器
*/
/**
* * 重写这个方法的目的:能够拦截所有Push进来的控制器
* @param viewController 即将push进来的控制器
*/
-(void)pushViewController:(UIViewController
*)viewController animated:(BOOL)animated{
if (self.viewControllers.count
> 0) {//这时pushi进来的控制器
viewController,不是第一个自控制器 (不是跟控制器)
/* 自动显示和隐藏tabbar */
/* 自动显示和隐藏tabbar */
viewController.hidesBottomBarWhenPushed =
YES;
/*
设置导航栏上面的内容 */
//设置左侧按钮
viewController.navigationItem.leftBarButtonItem
= [UIBarButtonItemitemWithTarget:selfaction:@selector(back)
image:@"navigationbar_back"highImage:@"navigationbar_back_highlighted"];
//设置右侧按钮
viewController.navigationItem.rightBarButtonItem = [UIBarButtonItemitemWithTarget:selfaction:@selector(more) image:@"navigationbar_more"highImage:@"navigationbar_more_highlighted"];
}
viewController.navigationItem.rightBarButtonItem = [UIBarButtonItemitemWithTarget:selfaction:@selector(more) image:@"navigationbar_more"highImage:@"navigationbar_more_highlighted"];
}
[superpushViewController:viewController
animated:animated];
}
-(void)back{
[selfpopViewControllerAnimated:YES];
}
-(void)more{
[selfpopToRootViewControllerAnimated:YES];
}
四 控件的封装
项目中某些模块的控件需要实现复杂的功能,并且整个项目中有多个模块用到该控件,那么就要实现控件的封装,比如:首页(Home)的标题点击实现下拉菜单的功能,上述tabBar的封装,发现(Search)的搜索框都可以单独封装使用。
下拉菜单
#import
"MCTitleMenuView.h"
@interfaceMCTitleMenuView ()
{
UIImageView *_menuView;
}
@interfaceMCTitleMenuView ()
{
UIImageView *_menuView;
}
@end
@implementation MCTitleMenuView
+(instancetype)menu{
return [[selfalloc]init];
}
-(void)showSelf:(UIButton*)btn{
//1.获取最上面的窗口
UIWindow *window = [[UIApplicationsharedApplication].windowslastObject];
//2.添加自己到窗口
[window
addSubview:self];
//3.设置尺寸
self.frame = window.bounds;
self.backgroundColor
= [UIColorclearColor];
self.userInteractionEnabled
= YES;
_menuView = [[UIImageViewalloc]initWithFrame:CGRectMake(20,
80,
200,
300)];
//调节下拉菜单的位置
CGRect newRect = [btn convertRect:btn.boundstoView:nil];
CGRect newRect = [btn convertRect:btn.boundstoView: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);
self.content.frame = CGRectMake(15, 25, _menuView.width - 30, _menuView.height - 40);
_content.layer.cornerRadius
= 5;
[_menuViewaddSubview:_content];
}
}
_menuView.image
= [UIImageimageNamed:@"popover_background"];
[selfaddSubview:_menuView];
}
-(void)dismis{
[_menuViewremoveFromSuperview];
[selfremoveFromSuperview];
}
-(void)setContent:(UIView *)content{
_content = content;
}
-(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;
[selfdismis];
}
}else{
if (touch.view != _menuView) {
[selfdismis];
}
}else{
if (touch.view != _menuView) {
_showButton.selected =
NO;
[selfdismis];
}
}
}
}
}
搜索框
#import
"MCSearchTextField.h"
@implementation MCSearchTextField
- (instancetype)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
[selfcreatSearchTextfield];
}
returnself;
}
@implementation MCSearchTextField
- (instancetype)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
[selfcreatSearchTextfield];
}
returnself;
}
-(void)creatSearchTextfield{
self.background
= [UIImageimageNamed:@"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;
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