1:Class Extension 还能巧妙的解决一个接口暴露问题

有些属性或者方法对外可以提供,有些只针对内部的类进行调用;

// Sark.framework/Sark.h
@interface Sark : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *creditCardPassword; // secret!
@end // Sark.framework/PrivateSarkWife.h
@interface PrivateSarkWife : NSObject
- (void)robAllMoneyFromCreditCardOfSark:(Sark *)sark; // needs password!
@end

假设 Sark.h 是 Sark.framework 唯一暴露的 Header,而 framework 中的一个私有类需要获取这个公共类的某个属性(或方法)该怎么办?PrivateSarkWife为Sark.framework内部一个类;上面的 creditCardPassword 属性需要一个对外不可见而对内可见的地方声明,这时候可以利用 Class Extension:

// Sark.h
@interface Sark : NSObject
@property (nonatomic, copy) NSString *name;
@end // Sark+Internal.h <--- new
@interface Sark ()
@property (nonatomic, copy) NSString *creditCardPassword;
@end // Sark.m
#import "Sark.h"
#import "Sark+Internal.h" // <--- new

将对公业务和对私业务用 Class Extension 的形式拆到两个 Header 中,在Sark.m里把两个头文件都进行引用,CreditCardPassword被定义在Sark+Internal.h的头文件里面,这样私有类对私有属性的依赖就被成功隔离开了:

// PrivateSarkWife.m
#import "PrivateSarkWife.h"
#import "Sark+Internal.h" // <--- 私有依赖 @implementation PrivateSarkWife
- (void)robAllMoneyFromCreditCardOfSark:(Sark *)sark {
NSString *password = sark.creditCardPassword; // oh yeah!
}
@end

2:UIScrollView知识点

- (void)viewDidLoad
{
[super viewDidLoad]; scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(, , , )];
scrollView.backgroundColor = [UIColor redColor];
// 是否支持滑动最顶端
// scrollView.scrollsToTop = NO;
scrollView.delegate = self;
// 设置内容大小
scrollView.contentSize = CGSizeMake(, *);
// 是否反弹
// scrollView.bounces = NO;
// 是否分页
// scrollView.pagingEnabled = YES;
// 是否滚动
// scrollView.scrollEnabled = NO;
// scrollView.showsHorizontalScrollIndicator = NO;
// 设置indicator风格
// scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
// 设置内容的边缘和Indicators边缘
// scrollView.contentInset = UIEdgeInsetsMake(0, 50, 50, 0);
// scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 50, 0, 0);
// 提示用户,Indicators flash
[scrollView flashScrollIndicators];
// 是否同时运动,lock
scrollView.directionalLockEnabled = YES;
[self.view addSubview:scrollView]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
label.backgroundColor = [UIColor yellowColor];
label.text = @"学习scrolleview";
[scrollView addSubview:label];
[label release];
} #pragma mark -
/*
// 返回一个放大或者缩小的视图
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{ }
// 开始放大或者缩小
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:
(UIView *)view
{ } // 缩放结束时
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{ } // 视图已经放大或缩小
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
NSLog(@"scrollViewDidScrollToTop");
}
*/ // 是否支持滑动至顶部
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
return YES;
} // 滑动到顶部时调用该方法
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
NSLog(@"scrollViewDidScrollToTop");
} // scrollView 已经滑动
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"scrollViewDidScroll");
} // scrollView 开始拖动
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(@"scrollViewWillBeginDragging");
} // scrollView 结束拖动
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
NSLog(@"scrollViewDidEndDragging");
} // scrollView 开始减速(以下两个方法注意与以上两个方法加以区别)
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
NSLog(@"scrollViewWillBeginDecelerating");
} // scrollview 减速停止
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(@"scrollViewDidEndDecelerating");
}

3:仿网易滚动菜单及内容视图滚动效果

#import "NewsViewController.h"

#import "VideoViewController.h"
#import "ReaderViewController.h"
#import "ScienceViewController.h"
#import "SocietyViewController.h"
#import "HotViewController.h"
#import "TopLineViewController.h" #import "TitleButton.h" #define ScreenW [UIScreen mainScreen].bounds.size.width
#define ScreenH [UIScreen mainScreen].bounds.size.height @interface NewsViewController ()<UIScrollViewDelegate> @property (nonatomic, strong) UIButton *selButton; @property (nonatomic, strong) NSMutableArray *titleBtns; // 标题滚动view
@property (weak, nonatomic) IBOutlet UIScrollView *titileScrollView; // 内容滚动view
@property (weak, nonatomic) IBOutlet UIScrollView *contentView; @end @implementation NewsViewController - (NSMutableArray *)titleBtns
{
if (_titleBtns == nil) {
_titleBtns = [NSMutableArray array];
}
return _titleBtns;
} // 头条,热点,视频,社会,订阅,科技(science) - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. // 添加所有子控制器
[self setUpChildViewController]; // 设置标题
[self setUpTitle]; // iOS7之后,导航控制器下所有ScrollView都会添加额外滚动区域
self.automaticallyAdjustsScrollViewInsets = NO; // 初始化scrollView
[self setUpScrollView]; } - (void)setUpScrollView
{
self.titileScrollView.showsHorizontalScrollIndicator = NO; self.contentView.contentSize = CGSizeMake(self.childViewControllers.count * [UIScreen mainScreen].bounds.size.width, ); self.contentView.showsHorizontalScrollIndicator = NO;
self.contentView.pagingEnabled = YES;
self.contentView.bounces = NO; self.contentView.delegate = self;
} - (void)setUpChildViewController
{ TopLineViewController *topLineVc = [[TopLineViewController alloc] init];
topLineVc.title = @"头条";
[self addChildViewController:topLineVc]; HotViewController *hotVc = [[HotViewController alloc] init];
hotVc.title = @"热点";
[self addChildViewController:hotVc]; VideoViewController *videoVc = [[VideoViewController alloc] init];
videoVc.title = @"视频";
[self addChildViewController:videoVc]; SocietyViewController *societyVc = [[SocietyViewController alloc] init];
societyVc.title = @"社会";
[self addChildViewController:societyVc]; ReaderViewController *readerVc = [[ReaderViewController alloc] init];
readerVc.title = @"订阅";
[self addChildViewController:readerVc]; ScienceViewController *scienceVc = [[ScienceViewController alloc] init];
scienceVc.title = @"科技";
[self addChildViewController:scienceVc];
} // 设置标题
- (void)setUpTitle
{
NSUInteger count = self.childViewControllers.count; CGFloat btnX = ;
CGFloat btnY = ;
CGFloat btnW = ;
CGFloat btnH = ; for (NSUInteger i = ; i < count; i++) {
btnX = i * btnW;
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.tag = i;
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
UIViewController *vc = self.childViewControllers[i];
[btn setTitle:vc.title forState:UIControlStateNormal];
[btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
[btn addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside]; [self.titileScrollView addSubview:btn]; [self.titleBtns addObject:btn];
// 默认选中第一个
if (i == ) {
[self titleClick:btn]; }
} self.titileScrollView.contentSize = CGSizeMake(btnW * count, ); } // 点击标题按钮
- (void)titleClick:(UIButton *)btn
{ // 0.设置标题按钮居中
[self setUpTitleBtnMiddle:btn]; // 1.滚动到对应的界面
CGFloat offsetX = btn.tag * ScreenW; self.contentView.contentOffset = CGPointMake(offsetX, ); // 2.添加对应子控制器view到对应的位置
UIViewController *vc = self.childViewControllers[btn.tag]; vc.view.frame = CGRectMake(offsetX, , ScreenW, self.contentView.bounds.size.height); // NSLog(@"%@",NSStringFromCGRect(self.contentView.bounds));
[self.contentView addSubview:vc.view]; // 还原之前标题的形变
[self setSelectBtn:btn]; } - (void)setSelectBtn:(UIButton *)btn
{
_selButton.transform = CGAffineTransformIdentity;
[_selButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_selButton.selected = NO; btn.transform = CGAffineTransformMakeScale(1.3, 1.3);
btn.selected = YES; _selButton = btn; } #pragma mark - UIScrollViewDelegate
// 减速完成的时候
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
// 获取当前的偏移量
CGFloat offsetX = scrollView.contentOffset.x;
// 获取页码
int page = offsetX / scrollView.bounds.size.width; UIButton *btn = self.titileScrollView.subviews[page]; // 选中按钮
[self setSelectBtn:btn]; // 设置按钮居中
[self setUpTitleBtnMiddle:btn]; // 添加对应子控制器到界面上
UIViewController *vc = self.childViewControllers[page]; // 已经加载的view就不需要添加了
if (vc.isViewLoaded) return; vc.view.frame = CGRectMake(offsetX , , self.contentView.bounds.size.width, self.contentView.bounds.size.height); [self.contentView addSubview:vc.view];
} // 设置标题按钮居中
- (void)setUpTitleBtnMiddle:(UIButton *)btn
{ // 计算偏移量
CGFloat offsetX = btn.center.x - ScreenW * 0.5; // 左边偏移多了,表示需要往左边看,可视范围往左边,偏移量就减少,最少应该是0
if (offsetX < ) offsetX = ;
CGFloat maxOffsetX = self.titileScrollView.contentSize.width - ScreenW; // 右边偏移多了,表示需要往右边看,可视范围往又边,偏移量就增加,最大不超过内容范围 - 屏幕宽度
if (offsetX > maxOffsetX) offsetX = maxOffsetX; [self.titileScrollView setContentOffset:CGPointMake(offsetX, ) animated:YES]; } // 监听内容view滚动
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat page = scrollView.contentOffset.x / scrollView.bounds.size.width; NSInteger leftIndex = page; // 右边缩放比例
CGFloat rightScale = (page - leftIndex);
// 左边缩放比例
CGFloat leftScale = ( - rightScale); NSInteger rightIndex = leftIndex + ; // 获取左边按钮
TitleButton *leftBtn = self.titleBtns[leftIndex]; NSInteger count = self.titleBtns.count; // 获取右边按钮
TitleButton *rightBtn; if (rightIndex < count) {
rightBtn = self.titleBtns[rightIndex];
} // 设置尺寸
CGFloat leftTransform = leftScale * 0.3 + ; // 1 ~ 1.3
CGFloat rightTransform = rightScale * 0.3 + ; // 1 ~ 1.3
leftBtn.transform = CGAffineTransformMakeScale(leftTransform, leftTransform);
rightBtn.transform = CGAffineTransformMakeScale(rightTransform, rightTransform); // 设置颜色
/*
RGB 红色: 1 0 0
黑色: 0 0 0
*/ UIColor *leftColor = [UIColor colorWithRed:leftScale green: blue: alpha:];
UIColor *rightColor = [UIColor colorWithRed:rightScale green: blue: alpha:]; [leftBtn setTitleColor:leftColor forState:UIControlStateNormal];
[rightBtn setTitleColor:rightColor forState:UIControlStateNormal]; } @end

效果图如下:

内外分离接口依赖及UIScrollView知识点的更多相关文章

  1. Mock接口依赖的使用

    mock 能做什么 1.前后端联调,如果你是一个前端页面开发,现在需要开发一个功能:下一个订单,支付页面的接口,根据支付结果,支付成功,展示支付成功页,支付失败,展示支付失败页.要完成此功能,你需要 ...

  2. python接口测试中常见的两种接口依赖处理方式

    一.请求体的字段依赖 这种情况多数是在当前测试的接口,它的前置接口的请求体中的字段要拿来在当前的接口请求体中继续使用,比如修改用户信息的接口,该接口会使用到用户名的字段,该字段是由创建用户时的请求体中 ...

  3. Postman实现数字签名,Session依赖, 接口依赖, 异步接口结果轮询

    Script(JS)为Postman赋予无限可能 基于Postman 6.1.4 Mac Native版 演示结合user_api_demo实现 PS 最近接到任务, 要把几种基本下单接口调试和持续集 ...

  4. mock 处理接口依赖

    1.输出配置文件如下 login.json [{ "request": { "uri": "/login", "method&qu ...

  5. Jmeter之接口依赖

    一.应用场景 1.现在有两个接口,一个是登录,一个查询,但查询接口必须要依赖登录接口的token,那么通过正则表达式提取器提取登录接口的响应结果 2.现在有两个接口,A接口返回列表数据,另一个查询接口 ...

  6. 前后端分离&接口API设计学习报告

    接口API设计学习报告 15331023 陈康怡 什么是API? API即Application Programming Interface.API是一种通道,负责一个程序与另一个程序的沟通.而对于w ...

  7. Postman 使用技巧之多环境测试及接口依赖关系处理

    一.前言 在日常开发中,除了正常的单元测试,某些情况我们还需要测试 HTTP 接口,团队中目前使用的是「 Postman 」这款 API调试 . HTTP 请求工具.通常我们将经常要测试的接口按照项目 ...

  8. FastAPI + Vue 前后端分离 接口自动化测试工具 apiAutoTestWeb

    apiAutoTestWeb使用说明 apiAutoTestWeb是为apiAutoTest的可视化版本,其采用前后端分离(FastAPI + Vue2)方式实现 具体使用: Python3 + Fa ...

  9. python使用正则+jsonpath处理接口依赖

    1.接口2的入参值依赖接口1的响应结果,如接口2的入参ids需要拿到接口1响应结果的id字段值,测试用例写在excel中,参数:{"ids":"${$..id}$&quo ...

随机推荐

  1. HT for Web基于HTML5的图像操作(一)

    HT for Web独创的矢量图片设计架构,使其具有强大丰富的动态图形呈现能力,但从最近知乎热议的“Adobe Photoshop 是否已经过时?”的话题,大家能体会到很多情况下实际项目不可能完全采用 ...

  2. JS魔法堂:jQuery.Deferred(jQuery1.5-2.1)源码剖析

    一.前言 jQuery.Deferred作为1.5的新特性出现在jQuery上,而jQuery.ajax函数也做了相应的调整.因此我们能如下的使用xhr请求调用,并实现事件处理函数晚绑定. var p ...

  3. If WCF Service side and Client side config is different?!

    from stackoverflow http://stackoverflow.com/questions/4879310/when-setting-up-a-wcf-client-and-serve ...

  4. qrcodenet 代码中一些基础的认识 帮助

    1): gRender.WriteToStream(matrix, ImageFormat.Png, stream, new Point(600, 600)); new Point(600, 600) ...

  5. Bootstrap学习笔记系列5------Bootstrap图片显示

    通过添加一下的class来实现bootstrap对图片的支持 img-round 通过border-radius:6px 来获得图片圆角 img-circle 通过border-radius:50%来 ...

  6. RabbitMQ入门教程——工作队列

    什么是工作队列 工作队列是为了避免等待一些占用大量资源或时间操作的一种处理方式.我们把任务封装为消息发送到队列中,消费者在后台不停的取出任务并且执行.当运行了多个消费者工作进程时,队列中的任务将会在每 ...

  7. C# Redis使用之StackExchange

    第1章   安装 在.NET平台使用Redis需要做如下准备工作: 创建一个新的Visual Studio应用或者打开一个已经存在的Visual Studio应用. 打开NuGet程序包 搜索并添加S ...

  8. Android使用SAX解析XML(5)

    parse_handler.java文件: package com.hzhi.my_sax; import org.xml.sax.Attributes; import org.xml.sax.SAX ...

  9. 对Java并发编程的几点思考

    1. Threads 和 Runnables 所有的现代操作系统都通过进程和线程来支持并发.进程是通常彼此独立运行的程序的实例,比如,如果你启动了一个Java程序,操作系统产生一个新的进程,与其他程序 ...

  10. ThinkCMF-首页Nav部分菜单配置详解

    Nav菜单代码放在了 /themes/simplebootx/Public/nav.html 具体代码: <?php $effected_id="main-menu"; $f ...