111iOS入门

02.项目实战 百思不得姐 自定义导航条,广告界面

2016-01-25  本文已影响782人  Liwx

@(iOS 项目实战)[项目实战]


目录


1.设置TabBarItem标题颜色,文字大小

使用appearance统一设置TabBarItem的颜色

// ----------------------------------------------------------------------------
// 加载类进内存的时候调用,只会调用一次(子类不会加载的适合不再加载父类的load方法)
+ (void)load
{
    // 谁才能使用appearance?只要遵守了这个UIAppearance协议,就能调用appearance
    // 注意:UIAppearance并不是所有属性都能设置
    // 哪些属性可以通过UIAppearance设置?只要属性有UI_APPEARANCE_SELECTOR这个宏描述,就可以使用UIAppearance设置
    // UIAppearance使用场景
    
    // 一次性设置tabBarItem字体颜色
    // ------------------------------------------------------------------------
    // 1.判断是否是WXTabBarController类
    // 1.1 获取item
    UITabBarItem *item = [UITabBarItem appearanceWhenContainedIn:self, nil];
    
    // 1.2 设置
    NSDictionary *attrSelected = @{NSForegroundColorAttributeName : [UIColor blackColor]};
    [item setTitleTextAttributes:attrSelected forState:UIControlStateSelected];
    
    // ----------------------------------------------------------------------------
    // 2.设置普通状态下的TabBar字体大小, 注意:一定要先设置正常状态下字体大小
    NSDictionary *attrNormal = @{NSFontAttributeName : [UIFont systemFontOfSize:13]};
    [item setTitleTextAttributes:attrNormal forState:UIControlStateNormal];
    
}

2.设置导航条按钮

多个控制器设置导航条按钮都要设置UIBarButtonItem,所有抽取设置UIBarButtonItem信息的分类

抽取UIBarButtonItem分类

3.统一设置导航条标题字体和背景图片

// ----------------------------------------------------------------------------
// 第一次加载到内存调用,只会调用一次,在load方法中统一设置导航条的背景图片和标题文字大小
+ (void)load
{
    // 1.获取全局的导航条
    UINavigationBar *navBar = [UINavigationBar appearanceWhenContainedIn:self, nil];
    
    // 2.设置导航条标题文字大小
    NSDictionary *titleAttr = @{NSFontAttributeName : [UIFont systemFontOfSize:20]};
    [navBar setTitleTextAttributes:titleAttr];
    
    // 3.设置导航条背景图片:一定要是UIBarMetricsDefault
    // iOS8和iOS9适配: iOS9之前:UIBarMetricsDefault,导航控制器跟控制器的view尺寸会减少64,iOS9就没有减少64了
    [navBar setBackgroundImage:[UIImage imageNamed:@"navigationbarBackgroundWhite"] forBarMetrics:UIBarMetricsDefault];
}

4.统一设置返回按钮

如果通过自定义导航条返回按钮,则导航控制器默认的边缘滑动返回效果失效.

设置返回按钮的位置,调整返回按钮的边距

// ----------------------------------------------------------------------------
// 重写pushViewController:方法,在跳转前统一设置返回按钮
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // ------------------------------------------------------------------------
    // 1.判断如果不是根控制器,则设置viewController控制器返回按钮
    if (self.childViewControllers.count > 0) {
        
        viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem backItemWithImage:[UIImage imageNamed:@"navigationButtonReturn"] highImage:[UIImage imageNamed:@"navigationButtonReturnClick"] target:self action:@selector(back) title:@"返回"];
    }
    
    [super pushViewController:viewController animated:animated];
}

跳转控制器出现黑色卡顿现象解决方案

5.设置手势滑动返回

边缘滑动返回


// 如果直接将系统手势清空,会有返回效果,但是在根控制器边缘滑动会导致出现假死状态,该方法不可行
    self.interactivePopGestureRecognizer.delegate = nil;
- (void)viewDidLoad {
    [super viewDidLoad];
 
    // // 恢复系统手势边缘滑动返回方式二(可行)
    self.interactivePopGestureRecognizer.delegate = self;
    
}

// ----------------------------------------------------------------------------
// 监听系统滑动手势,如果返回YES表示
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    // 设置只有在非根控制器滑动有效,因为如果根控制器滑动如果触发手势会调用pop,根控制器不能再pop,会导致假死.
    return self.childViewControllers.count > 1;
}

全屏滑动返回

只要触发UIScreenEdgePanGestureRecognizer,就会调用_UINavigationInteractiveTransition的handleNavigationTransition:
_UINavigationInteractiveTransition的handleNavigationTransition有滑动返回功能

    系统手势打印结果:
    NSLog(@"%@", self.interactivePopGestureRecognizer);
    
    <UIScreenEdgePanGestureRecognizer: 0x7feab3e30c40; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7feab3c8fb10>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7feab3e306d0>)>>
    
    
    系统手势代理打印结果:
    NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
    
    <_UINavigationInteractiveTransition: 0x7feab3e306d0>
    
    打印结果分析: 系统手势代理是
#pragma =======================================================================
#pragma mark - 设置滑动返回手势
- (void)viewDidLoad {
    [super viewDidLoad];
 
    // 恢复系统手势边缘滑动返回方式一(不可行)
    // 如果直接将系统手势清空,会有返回效果,但是在根控制器边缘滑动会导致出现假死状态,该方法不可行
//    self.interactivePopGestureRecognizer.delegate = nil;
    
    // // 恢复系统手势边缘滑动返回方式二(可行)
//    self.interactivePopGestureRecognizer.delegate = self;
    
    
    // 添加全屏滑动手势
    
    /** 
     系统手势打印结果:
     NSLog(@"%@", self.interactivePopGestureRecognizer);
     
     <UIScreenEdgePanGestureRecognizer: 0x7feab3e30c40; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7feab3c8fb10>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7feab3e306d0>)>>
     
     
     系统手势代理打印结果:
     NSLog(@"%@", self.interactivePopGestureRecognizer.delegate);
     
     <_UINavigationInteractiveTransition: 0x7feab3e306d0>
     
     打印结果分析: 系统手势代理是
     
     */
    
    // 1.获取方法的调用者
    id target = self.interactivePopGestureRecognizer.delegate;
    
    // 2.给系统的view添加手势,监听到手势调用原来系统手势代理调用的方法
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
    // 2.1 设置手势代理,用于在代理方法中设置非控制器才能滑动返回
    pan.delegate = self;
    [self.view addGestureRecognizer:pan];
    
    // 3.取消系统手势
    self.interactivePopGestureRecognizer.enabled = NO;
}

// ----------------------------------------------------------------------------
// 监听系统滑动手势,如果返回YES表示允许滑动手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    // 设置只有在非根控制器滑动有效,因为如果根控制器滑动如果触发手势会调用pop,根控制器不能再pop,会导致假死.
    return self.childViewControllers.count > 1;
}

6.广告界面的搭建

广告界面xib搭建

广告界面xib布局.png

7.广告界面的功能实现

广告界面第三方框架AFNetworking,MJExtension,SDWebImage的使用

    // ------------------------------------------------------------------------
    // 1.创建请求回话管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    // ------------------------------------------------------------------------
    // 2. 设置响应体的数据格式,添加@"text/html"
    AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
    serializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil];
    manager.responseSerializer = serializer;
    
    // ------------------------------------------------------------------------
    // 3.拼接请求参数
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    parameters[@"code2"] = code2;
    
    // ------------------------------------------------------------------------
    // 4.请求广告数据
    [manager GET:@"http://mobads.baidu.com/cpro/ui/mads.php" parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"请求成功");
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@", error);
    }];

获取广告数据

 if ([[UIApplication sharedApplication] canOpenURL:url]);
#import "WXAdViewController.h"
#import <MJExtension.h>
#import <UIImageView+WebCache.h>
#import <AFNetworking.h>
#import "WXTabBarController.h"
#import "WXAdItem.h"

static NSString * const code2 = @"phcqnauGuHYkFMRquANhmgN_IauBThfqmgKsUARhIWdGULPxnz3vndtkQW08nau_I1Y1P1Rhmhwz5Hb8nBuL5HDknWRhTA_qmvqVQhGGUhI_py4MQhF1TvChmgKY5H6hmyPW5RFRHzuET1dGULnhuAN85HchUy7s5HDhIywGujY3P1n3mWb1PvDLnvF-Pyf4mHR4nyRvmWPBmhwBPjcLPyfsPHT3uWm4FMPLpHYkFh7sTA-b5yRzPj6sPvRdFhPdTWYsFMKzuykEmyfqnauGuAu95Rnsnbfknbm1QHnkwW6VPjujnBdKfWD1QHnsnbRsnHwKfYwAwiu9mLfqHbD_H70hTv6qnHn1PauVmynqnjclnj0lnj0lnj0lnj0lnj0hThYqniuVujYkFhkC5HRvnB3dFh7spyfqnW0srj64nBu9TjYsFMub5HDhTZFEujdzTLK_mgPCFMP85Rnsnbfknbm1QHnkwW6VPjujnBdKfWD1QHnsnbRsnHwKfYwAwiuBnHfdnjD4rjnvPWYkFh7sTZu-TWY1QW68nBuWUHYdnHchIAYqPHDzFhqsmyPGIZbqniuYThuYTjd1uAVxnz3vnzu9IjYzFh6qP1RsFMws5y-fpAq8uHT_nBuYmycqnau1IjYkPjRsnHb3n1mvnHDkQWD4niuVmybqniu1uy3qwD-HQDFKHakHHNn_HR7fQ7uDQ7PcHzkHiR3_RYqNQD7jfzkPiRn_wdKHQDP5HikPfRb_fNc_NbwPQDdRHzkDiNchTvwW5HnvPj0zQWndnHRvnBsdPWb4ri3kPW0kPHmhmLnqPH6LP1ndm1-WPyDvnHKBrAw9nju9PHIhmH9WmH6zrjRhTv7_5iu85HDhTvd15HDhTLTqP1RsFh4ETjYYPW0sPzuVuyYqn1mYnjc8nWbvrjTdQjRvrHb4QWDvnjDdPBuk5yRzPj6sPvRdgvPsTBu_my4bTvP9TARqnam";

@interface WXAdViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *launchImageView;
@property (weak, nonatomic) IBOutlet UIView *adView;
@property (weak, nonatomic) IBOutlet UIButton *jumpButton;

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) WXAdItem *adItem;
@end

@implementation WXAdViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1.设置启动图片,屏幕适配
    [self setupLaunchImageView];
    
    // 2.请求广告数据
    [self loadAdData];
    
    // 3.创建定时器
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    [self timeChange];
}

#pragma =======================================================================
#pragma mark - 启动图片屏幕适配,请求广告数据,定时器

// ----------------------------------------------------------------------------
// 设置启动图片,屏幕适配,根据屏幕的高度
- (void)setupLaunchImageView
{
    UIImage *image = nil;
    // ------------------------------------------------------------------------
    // 适配启动背景图片
    if (iPhone4) {
        image = [UIImage imageNamed:@"LaunchImage"];
    } else if (iPhone5) {
        image = [UIImage imageNamed:@"LaunchImage-568h"];
    } else if (iPhone6) {
        image = [UIImage imageNamed:@"LaunchImage-800-667h"];
    } else if (iPhone6p) {
        image = [UIImage imageNamed:@"LaunchImage-800-Portrait-736h@3x"];
    }
    
    // 设置启动背景图片
    self.launchImageView.image = image;
}

// ----------------------------------------------------------------------------
// 请求广告数据
- (void)loadAdData
{
    // ------------------------------------------------------------------------
    // 1.创建请求回话管理者
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    // ------------------------------------------------------------------------
    // 2. 设置响应体的数据格式,添加@"text/html"
    AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
    serializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil];
    manager.responseSerializer = serializer;
    
    // ------------------------------------------------------------------------
    // 3.拼接请求参数
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    parameters[@"code2"] = code2;
    
    // ------------------------------------------------------------------------
    // 4.请求广告数据
    [manager GET:@"http://mobads.baidu.com/cpro/ui/mads.php" parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        // 判断取回来的数据是否正确
        
        // 4.1 获取广告数据 ,返回的广告数据是数组,有[],所以要用lastObject取出数据
        NSDictionary *adDict = [responseObject[@"ad"] lastObject];
        
        // 判断是否请求到数据,如果没有数据,则退出
        if (adDict == nil) {
            return;
        }
        // 4.2 字典转模型 mj_objectWithKeyValues:方法作用是将字典转换成对应的模型
        WXAdItem *adItem = [WXAdItem mj_objectWithKeyValues:adDict];
        self.adItem = adItem;
        
        // 4.3 设置广告界面的数据,返回数据中有广告图片的尺寸
        CGFloat w = screenW;
        CGFloat h = screenW / adItem.w * adItem.h;
        UIImageView *adImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, w, h)];
        [adImageView sd_setImageWithURL:[NSURL URLWithString:adItem.w_picurl]];
        [self.adView addSubview:adImageView];
        adImageView.userInteractionEnabled = YES;
        
        // 4.4 添加点击手势,点击图片跳转到广告页
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
        [adImageView addGestureRecognizer:tap];
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@", error);
    }];
  
}

// ----------------------------------------------------------------------------
// 定时更新按钮的标题,定时时间到则跳转
- (void)timeChange
{
    static NSInteger timeIndex = 3;
    // 更新跳过按钮标题
    [self.jumpButton setTitle:[NSString stringWithFormat:@"跳过 (%ld)", timeIndex] forState:UIControlStateNormal];
    
    if (timeIndex-- < 0) {
        [self.timer invalidate];
        [self jump];
    }
}


#pragma =======================================================================
#pragma mark - 跳过按钮点击, 点击广告图片跳转
// ----------------------------------------------------------------------------
// 监听点击跳过按钮
- (IBAction)jump {
    
    // 关闭定时器
    [self.timer invalidate];
    
    WXTabBarController *tabBarVc = [[WXTabBarController alloc] init];
    
    [UIApplication sharedApplication].keyWindow.rootViewController = tabBarVc;
}

// ----------------------------------------------------------------------------
// 监听广告图片点击
- (void)tap
{
    // 检查url是否能打开
    NSURL *url = [NSURL URLWithString:self.adItem.ori_curl];
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.adItem.ori_curl]];
    }
}

跳过按钮注意点

8.CocoaPods的介绍

CocoaPods:管理第三方框架

podfile文件:描述加载哪些第三方框架

Podfile.lock:第一次pod完,自动生成这个文件,记录当前需要加载框架的版本号
终端指令 -help 学习
pod install 1.判断下有没有Podfile.lock,如果有,根据Podfile.lock加载,没有,根据Podfile文件去加载
pod update 2.更新需要加载框架的版本号,并且创建新的Podfile.lock
--no-repo-update:不执行pod repo update
pod repo update : 更新仓库索引,获取所有框架最新版本
pod install --no-repo-update : 比较快速导入第三份框架

上一篇 下一篇

猜你喜欢

热点阅读