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. DirectoryHelper

    /// <summary> /// 将相对路径转换成程序所在的绝对路径 /// </summary> /// <param name="path"&g ...

  2. Android Studio的git功能的使用介绍

    本文介绍Android Studio(下面简称AS)中git工具的一些简单使用.因为AS为git的使用提供了很多人性化的图形界面操作,在很大程度上可以增加开发效率.本文面向新手,题主自己也是新手一枚, ...

  3. Wo的书单

    一个人,一生之中总要有几本证明自己的书. 2016---08 <ASP.NET MVC5 高级编程(第五版)> <数据结构(C语言第二版)>

  4. Bootstrap学习笔记系列1-------Bootstrap网格系统

    Bootstrap网格系统 学习笔记 [TOC] 简单网格 先上代码再解释 <!DOCTYPE html> <html> <head> <title>B ...

  5. C#遍历Dictionary

    C#遍历Dictionary方法 Dictionary<string, int> d = new Dictionary<string, int>(); foreach (Key ...

  6. SSO单点登录实现原理与总结

    一.什么是单点登录SSO(Single Sign-On) SSO是一种统一认证和授权机制,指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用 ...

  7. 第 26 章 CSS3 动画效果

    学习要点: 1.动画简介 2.属性详解 3.简写和版本 主讲教师:李炎恢 本章主要探讨 HTML5 中 CSS3 的动画效果,可以通过类似 Flash 那样的关键帧模式控制运行. 一.动画简介 CSS ...

  8. 2016暑假多校联合---Counting Intersections

    原题链接 Problem Description Given some segments which are paralleled to the coordinate axis. You need t ...

  9. mongodb命令使用大全(常用命令)

    数据库常用命令 1.Help查看命令提示 help db.help(); db.yourColl.help(); db.youColl.find().help(); rs.help(); 2.切换/创 ...

  10. winform 固定splitContainer某一部分大小

    处于布局省事考虑,通常会用splitcontainer进行总体的布局,例如: 默认情况下,splitcontainer在运行时会根据上下文自动调整每个panel的大小,但大部分情况下,其实我们希望左边 ...