给UIScrollView添加category实现UIScrollView的轮播效果
大家都知道,要给category添加属性是必须通过runtime来实现的,本教程中给UIScrollView添加category添加了好几个属性,也是通过runtime来实现的.
实现后的效果如下:
UIScrollView的category的源码为:
UIScrollView+YX.h + UIScrollView+YX.m
//
// UIScrollView+YX.h
// PageView
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "YXGCD.h"
@interface UIScrollView (YX)
@property (nonatomic, strong) NSNumber *currentPage; // 当前页码
@property (nonatomic, strong) NSNumber *largestPage; // 最大页码
@property (nonatomic, strong) NSNumber *timerInterval; // 时间间隔
@property (nonatomic, strong) GCDTimer *timer; // 定时器
- (void)start;
@end
//
// UIScrollView+YX.m
// PageView
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import "UIScrollView+YX.h"
#import <objc/runtime.h>
#define ANIMATION_DURATION 0.2
@implementation UIScrollView (YX)
static char timerFlag;
- (void)setTimer:(GCDTimer *)timer
{
objc_setAssociatedObject(self, &timerFlag,
nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, &timerFlag,
timer,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (GCDTimer *)timer
{
return objc_getAssociatedObject(self, &timerFlag);
}
static char currentPageFlag;
- (void)setCurrentPage:(NSNumber *)currentPage
{
objc_setAssociatedObject(self, ¤tPageFlag,
nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, ¤tPageFlag,
currentPage,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)currentPage
{
return objc_getAssociatedObject(self, ¤tPageFlag);
}
static char largestPageFlag;
- (void)setLargestPage:(NSNumber *)largestPage
{
objc_setAssociatedObject(self, &largestPageFlag,
nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, &largestPageFlag,
largestPage,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)largestPage
{
return objc_getAssociatedObject(self, &largestPageFlag);
}
static char timerIntervalFlag;
- (void)setTimerInterval:(NSNumber *)timerInterval
{
objc_setAssociatedObject(self, &timerIntervalFlag,
nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, &timerIntervalFlag,
timerInterval,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)timerInterval
{
return objc_getAssociatedObject(self, &timerIntervalFlag);
}
- (void)start
{
if (self.currentPage != nil && self.largestPage != nil && \
self.timerInterval != nil && self.timer != nil)
{
__weak UIScrollView *weakObj = self;
[self.timer event:^{
if (ceil(weakObj.contentOffset.x / weakObj.bounds.size.width) == \
weakObj.contentOffset.x / weakObj.bounds.size.width)
{
weakObj.currentPage = \
[NSNumber numberWithInt:weakObj.contentOffset.x / 320.f];
[UIView animateWithDuration:ANIMATION_DURATION animations:^{
CGPoint point = weakObj.contentOffset;
weakObj.currentPage = \
[NSNumber numberWithInt:[weakObj.currentPage intValue] + 1];
point.x = \
([weakObj.currentPage intValue] % [weakObj.largestPage intValue])\
*weakObj.bounds.size.width;
weakObj.contentOffset = point;
}];
}
} timeInterval:NSEC_PER_SEC * [self.timerInterval floatValue]];
[[GCDQueue mainQueue] execute:^{
[weakObj.timer start];
} afterDelay:NSEC_PER_SEC * [self.timerInterval floatValue]];
}
else
{
NSLog(@"请配置参数,亲:)");
}
}
@end
主函数中使用的源码:
RootViewController.m
//
// RootViewController.m
// PageView
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import "RootViewController.h"
#import "YXGCD.h"
#import "UIScrollView+YX.h"
@interface RootViewController ()<UIScrollViewDelegate>
@property (nonatomic, strong) GCDTimer *timer;
@property (nonatomic, assign) NSInteger currentPage;
@property (nonatomic, assign) NSInteger largestPage;
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
// 数据源
NSArray *array = @[@"YouXianMing", @"QiuLiang", @"LinKen", @"KeLinDun"];
// 初始化UIScrollView
UIScrollView *rootView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
rootView.pagingEnabled = YES;
rootView.contentSize = CGSizeMake(320*array.count, 320);
[self.view addSubview:rootView];
// 根据数据源加载控件
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UILabel *tmp = [[UILabel alloc] initWithFrame:CGRectMake(idx*320, 0, 320, 320)];
tmp.text = obj;
tmp.layer.borderWidth = 2.f;
tmp.textColor = [UIColor cyanColor];
tmp.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:30];
tmp.textAlignment = NSTextAlignmentCenter;
tmp.backgroundColor = [UIColor colorWithRed:arc4random()%100/100.f
green:arc4random()%100/100.f
blue:arc4random()%100/100.f
alpha:0.5f];
[rootView addSubview:tmp];
}];
// 设定参数值后开始轮播
rootView.timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
rootView.currentPage = [NSNumber numberWithInt:0];
rootView.largestPage = [NSNumber numberWithInt:array.count];
rootView.timerInterval = [NSNumber numberWithInt:4];
[rootView start];
}
@end
以下来详细讲解下设计的思路:
定时器是用来实现轮播用定时器,这个是最起码的条件:)
runtime添加属性请自行百度脑补或者找笔者之前的教程文章:)
start方法实现的一些细节需要注意:
以下是设计的最为核心的地方: