day05之“ScrollView”

来源:互联网 发布:视频相册的软件 编辑:程序博客网 时间:2024/06/05 19:04

前言

.getter、setter的重写细节

/** 图像的setter方法;setter方法,除了赋值,还执行了contentSize的设置动作 */- (void)setImage:(UIImage *)image{    //setter方法的第一个步骤:给属性进行赋值    _image = image;    //设置图像视图的内容    [self.imageView setImage:_image];    //让图像视图,根据图像大小,自动调整自己的视图大小    [self.imageView sizeToFit];//Resizes and moves the receiver view so it just encloses its subviews.    //告诉图像视图,内部内容实际的大小    [self.scrollView setContentSize:_image.size];}/** 0.getter 方法的重写 * 使用自身对象的时候,使用_属性名称进行获取 *使用其他成员属性的时候,使用self.gtter 方法,这样可以及时的实例化对用的成员属性 1.懒加载imageView属性,重写getter方法--使用对象dot属性名称的时候,会调用getter方法,_属性名称不会调用getter方法 */- (UIImageView *)imageView{    if (nil == _imageView) {        //创建imageView        UIImageView *tmpImageView = [[UIImageView alloc]init];        _imageView=tmpImageView;        [self.scrollView addSubview:_imageView];    }    return _imageView;}

零、 运行循环runloop

这里写图片描述

//往运行循环添加特定事件的目标和动作(add target/action for particular event)--- 使用UIControl 的addTarget:action:forControlEvents:方法    //将监听方法click注册到“运行循环”,当触发ControlEvent事件时,由“运行循环”通知Target(ViewController) 执行action(@selector)    //Adds a target and action for a particular event (or events) to an internal dispatch table.将特定事件的执行目标和行动添加到内部调度表    [btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside];
#pragma mark - 计时器的播放实现- (IBAction)start{    NSLog(@"%s",__FUNCTION__);    //间隔一秒更新counterLabel的显示    //计时器    //往运行循环添加timer的方式一:-------------------------------------------    /**     Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode.     参数说明     1》seconds: double 时间间隔     2》target: The object to which to send the message specified by aSelector when the timer fires. 监听时钟触发的对象     3》Selector: The message to send to target when the timer fires.调用的方法     The selector should have the following signature: timerFireMethod:     - (void)timerFireMethod:(NSTimer *)timer     4》userInfo:     The user info for the timer.通常为nil,可用于区分计时器     repeats:if YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires.是否重复     *///    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];    //将timer添加到运行循环的方式二-------------------------------------------    self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];    //Registers a given timer with a given input mode.NSRunLoopCommonModes (监听滚动模式)    [[NSRunLoop  currentRunLoop] addTimer:self.timer forMode: NSRunLoopCommonModes];}

一、掌握

1》UIScrollView的常见属性

这里写图片描述

//  ViewController.m//  20160316-喜马拉雅//  Created by devzkn on 3/16/16.//  Copyright © 2016 hisun. All rights reserved//#import "ViewController.h"@interface ViewController ()@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;@property (weak, nonatomic) IBOutlet UIButton *lastButton;@end@implementation ViewController/** 1.--setter方法的实现差别 contentSize 会根据ContentInset调整offset--除了赋值,还实现了其他动作 contentInset不会根据contentSize调整offset--单纯给属性赋值 */- (void)viewDidLoad {    [super viewDidLoad];    //1.设置间距:只是指定内容外侧的边距,并不会根据contentSize自动调整contentOffset    [self.scrollView setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];    //2.  设置滚动视图内容大小    //1> 若有间距contentInset,根据间距自动调整contentOffset    //2> 若无contentInset,contentOffset是(0,0)    [self.scrollView setContentSize:CGSizeMake(0, CGRectGetMaxY(self.lastButton.frame)+10)];//CGRectGetMaxY(self.lastButton.frame)+10) 是为了能更清楚的显示最后一个按钮    //3.设置偏移位置    [self.scrollView setContentOffset:CGPointMake(0, -64)];}@end

*因此在使用contentSize、contentInset、contentOffset的setter方法的时候,要注意先后顺序;想要准确的调整offset的话,可以先设置inset-》size;或者是:size-》offset
*storyBoard快速布局方法:使用option键,进行拖拽实现控件的copy

2》UI ScrollView的常用代理方法
3》UI Scrollview 的缩放
*在simulator上面操作缩放:按住option键即可
4》UI ScrollView和UIPageControl的分页实现方式
5》NSTimer 的使用
6》自动布局:Apple为了让程序员能够将注意力集中在程序上,而不用在代码中过多的使用frame。
*“参照” 任何一个控件,都可以参照另外一个控件定义出准确的位置

二、 什么是UIScrollView

是一个能滚动的视图控件,可以用来展示大量的内容,且通过滚动可以查看所有内容
1、UIScrollView 的基本使用 -- 解决UIScrollView 无法滚动的方法
1》 检查是否设置contentSize 属性
2》 检查scrollEnabled 属性值是否=NO
3》检查userInteractionEnabled 是否为NO
4》 取消outLayout 的功能:若是通过storyBoard中添加的scrollView控件,要想scrollView滚动的话,必须取消autoLayout。
2、UIScrollView的常见属性

@property(nonatomic) CGPoint contentOffset; //这个属性用来表示UIScrollView滚动的位置@property(nonatomic) CGSize contentSize; //这个属性用来表示UIScrollView内容的尺寸,滚动范围(能滚多远)@property(nonatomic) UIEdgeInsets contentInset; //这个属性能够在UIScrollView的4周增加额外的滚动区域

三、UIScrollView的delegate
0、代理的作用是什么?
1》》代理设计模式,在o c中使用最为广泛的一种设计模式;主要用来负责在两个对象之间,发生某些事件时,来传递消息或者数据
2》》监听哪些“不能通过addTarget方式监听“的事件

1.背景
1》目标:想再UIScrollView的正在滚动状态、滚动到某位置、停止滚动状态时做一些特定的动作
2》前提:监听UIScrollView 的滚动过程(事件)
3》实现方法:通过给UIScrollView 设置delegate对象,当UIScrollView发生一系列滚动的时候,会自动通知(发生特定消息亦即方法调用)它的代理对象
4》 成为delegate 对象的条件:遵守UIScrollViewDelegate的协议,并实现对应方法
--通常将UIScrollView 所在的ViewController设置为它的delegate对象

这里写图片描述

5》设置UIScrollView 的delegate属性的两者方法:
1》》通过代码实现:

使用修改scrollView对象的属性方式添加delegate 折叠原码
1

self.scrollView.delegate = self;

2》》:通过storyBoard的拖线

delegate 的例子:控制器希望知道用户输入的每一个字符!
这里写图片描述

代理小结:

1、代理实现的步骤:
1》》成为(子)控件的代理;--父亲(视图控制器)成为儿子(textField)的代理
2》》 遵守协议--》目的是利用Xcode的智能提示功能,快速编写代码--这个步骤可选
3》》实现协议方法
p s: 协议是由控件定义的,因为只有控件自己本身最了解自己内部发生的事件。

四、UIScrollView 的缩放原理
1. 当用户在UIScrollView身上使用捏合手势时,UIScrollView会给delegate对象发送一条消息,询问delegate究竟要缩放自己内部的哪个子控件(那一块内容)

- (void) scrollViewWillBeginZooming:(UIScrollView *)scrollView  withView:(UIView *)view;//准备开始缩放的时候调用- (void)scrollViewDidZoom:(UIScrollView *)scrollView;//正在缩放的时候调用

当用户使用捏合手势的时候,UIScrollView 会调用delegate对象的viewForZoomingInScrollView:方法,这个方法返回的控件就是需要进行缩放的控件。
2、缩放实现步骤:
1>设置UIScrollView的iddelegate对象
2》设置minimumZoomScale、MaximumZoomScale 缩小、放大的最大比例
3》delegate对象实现viewForZoomingInScrollView:方法,返回需要缩放的视图控件
ps:其他根缩放相关的delegate方法:

五、分页
只要将UIScrollView 的属性PageEnabled设为YES,UIScrollView会被分割成多个独立的页面,里面的内容就能进行分页展示
1》通常配合UIPageControl使用,来增强分页效果
1》》UIPageControl 的常见属性:

//一共有多少页@property(nonatomic) NSInteger numberOfPages;//当前显示的页码@property(nonatomic) NSInteger currentPage;//只有一页时,是否需要隐藏页码指示器@property(nonatomic) BOOL hidesForSinglePage;//其他页码指示器的颜色@property(nonatomic,retain) UIColor *pageIndicatorTintColor;//当前页码指示器的颜色@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor; 

六、NSTimer 定时器
1、作用:
1》》:在指定的时间,执指定的任务(方法、动作)
2》》:每隔一段时间,执行制定任务(action)
2.实现方法:
1》》开启一个定时任务,调用scheduleTimerWithTimeInterval:方法

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

每隔ti秒,调用一次aTarget的aSelector方法,yesOrNo决定了是否重复执行这个任务
1》》停止定时器工作 --调用invalidate:方法

- (void)invalidate;//n一旦定时器被停止了,就不能再次执行任务。只能再创建一个新的定时器才能执行新的任务
2.NSTimer准确吗?如果不准确,怎么办?1>>.NSTimer通常用来有一定时间跨度的周期性事件的处理!--》不准确2>>.CADisplayLink 与 NSTimer 有什么不同? IOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。--》解决方法,CADisplayLink适用于“时间间隔比较短“的事件处理*NSTimer的精确度就显得低了点,比如NSTimer的触发时间到的时候,runloop如果在阻塞状态,触发时间就会推迟到下一个runloop周期--》导致任务的叠加。并且 NSTimer新增了tolerance属性,让用户可以设置可以容忍的触发的时间的延迟范围。*CADisplayLink使用场合相对专一,适合做UI的不停重绘,比如自定义动画引擎或者视频播放的渲染。NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。在UI相关的动画或者显示内容使用 CADisplayLink比起用NSTimer的好处就是我们不需要在格外关心屏幕的刷新频率了,因为它本身就是跟屏幕刷新同步的。ps注意:1>通常来讲,iOS设备的刷新频率事60HZ也就是每秒60次。那么每一次刷新的时间就是1/60秒 大概16.7毫秒。当我们的frameInterval值为1的时候我们需要保证的是 CADisplayLink调用的`target`的函数计算时间不应该大于 16.7否则就会出现严重的丢帧现象。https://developer.apple.com/library/ios/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/index.html2>在mac应用中我们使用的不是CADisplayLink而是 CVDisplayLink它是基于C接口的用起来配置有些麻烦但是用起来还是很简单的。https://developer.apple.com/library/ios/samplecode/AVBasicVideoOutput/Introduction/Intro.html#//apple_ref/doc/uid/DTS400131092>一个类似Secret文字渐变效果的开源库https://github.com/zipme/RQShineLabel/tree/master/Example/RQShineLabelDemo

正文

一、UIKit 的复习,以及delegate 的介绍

////  ViewController.m//  20160313-UIKitReview////  Created by devzkn on 3/13/16.//  Copyright © 2016 hisun. All rights reserved.//#import "ViewController.h"@interface ViewController ()<UITextFieldDelegate>@end@implementation ViewController/** 1、UIButton -》UIControl-》UIView 1.1》 设置控件的状态 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIControl : UIView @property(nonatomic,getter=isEnabled) BOOL enabled;//启用、禁用控件 @property(nonatomic,getter=isSelected) BOOL selected;//选中、不选中 @property(nonatomic,getter=isHighlighted) BOOL highlighted; //高亮、不高亮 1.2》 设置控件内容的布局 @property(nonatomic) UIControlContentVerticalAlignment contentVerticalAlignment;//垂直居中方法 @property(nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment;//水平居中方向 1.3>添加监听方法 - (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; - (void)removeTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; 2.UILabel -》UIView 3、UIImageView-》UIView 4.UITextField-》UIControl-》UIView ****代理设计模式,是oc中最为广泛的一种设计模式 1》 代理的作用是什么?    *监听哪些“不能通过addTarget方式监听的“事件    *主要负责在,两对象之间,发生某些事件时,数据或消息的传递工作 2》代理实现的步骤  *成为(子)控件的代理;父亲(视图控制器)成为儿子(textField)的代理  *可选步骤:遵守协议,-》利用ide的提示功能,快速编写代码  *实现协议方法 */- (void)viewDidLoad {    [super viewDidLoad];    UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];    [btn setCenter:self.view.center];    [self.view addSubview:btn];    //将监听方法click注册到“运行循环”,当触发ControlEvent事件时,由“运行循环”通知Target(ViewController) 执行action(@selector)    //Adds a target and action for a particular event (or events) to an internal dispatch table.将特定事件的执行目标和行动添加到内部调度表    [btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];    UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 80, 20)];    [textField setText:@"lydia"];    [textField setTextColor:[UIColor blackColor]];    [textField setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];    [textField setDelegate:self];    [self.view addSubview:textField];}#pragma mark - 文本框代理/** 成为代理之后要做的事情是什么?以及如何工作 1》协议:一些预先定义的没有具体的实现方法名,每个方法对应不同的事件。@protocol UITextFieldDelegate <NSObject> *///Asks the delegate if the specified text should be changed.- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{    NSLog(@"replacementString =%@, textField = %@,NsRange = %@",string,textField.text,NSStringFromRange(range));    //限制输入的长度    long location = range.location;    return location<7;//YEStrue if the specified text range should be replaced; otherwise, NOfalse to keep the old text.}/** */- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{//    NSLog(@"%s",__FUNCTION__);    return YES;// if an editing session should be initiated}- (void)textFieldDidBeginEditing:(UITextField *)textField{//    NSLog(@"%s",__FUNCTION__);}- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{//    NSLog(@"%s",__FUNCTION__);    return YES;//if editing should stop}- (void)textFieldDidEndEditing:(UITextField *)textField{    NSLog(@"%s",__FUNCTION__);}- (BOOL)textFieldShouldClear:(UITextField *)textField{    NSLog(@"%s",__FUNCTION__);    return YES;//if the text field’s contents should be cleared;}- (BOOL)textFieldShouldReturn:(UITextField *)textField{    NSLog(@"%s",__FUNCTION__);    return YES;//if the text field should implement its default behavior for the return button;}- (void)click:(UIButton *)button{    NSLog(@"%s",__FUNCTION__);    [button removeTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];}
//  ViewController.m//  20160316-喜马拉雅//  Created by devzkn on 3/16/16.//  Copyright © 2016 hisun. All rights reserved.#import "ViewController.h"@interface ViewController ()@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;@property (weak, nonatomic) IBOutlet UIButton *lastButton;@end@implementation ViewController/** 1.--setter方法的实现差别(可采用设置断点进行查看) contentSize 会根据ContentInset调整offset--除了赋值,还实现了其他动作 contentInset不会根据contentSize调整offset--单纯给属性赋值 *///系统加载了storyBoard之后,调用setScrollView:方法对scrollView对象进行赋值- (void)setScrollView:(UIScrollView *)scrollView{//本方法先于viewDidLoad:执行;本方法由系统底层自动调用    _scrollView = scrollView;//1》setter 方法的第一句,就是赋值    //2》其他的动作    [_scrollView setContentInset:UIEdgeInsetsMake(64, 0, 10, 0)];    [_scrollView setContentSize:CGSizeMake(0, CGRectGetMaxY(self.lastButton.frame))];}/** 视图加载完成之后执行 */- (void)viewDidLoad {    [super viewDidLoad];    //1.设置间距:只是指定内容外侧的边距,并不会根据contentSize自动调整contentOffset//    [self.scrollView setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];    //2.  设置滚动视图内容大小    //1> 若有间距contentInset,根据间距自动调整contentOffset    //2> 若无contentInset,contentOffset是(0,0)//    [self.scrollView setContentSize:CGSizeMake(0, CGRectGetMaxY(self.lastButton.frame)+10)];//CGRectGetMaxY(self.lastButton.frame)+10) 是为了能更清楚的显示最后一个按钮    //3.设置偏移位置//    [self.scrollView setContentOffset:CGPointMake(0, -64)];}@end
////  ViewController.m//  20160317-倒计时////  Created by devzkn on 3/17/16.//  Copyright © 2016 hisun. All rights reserved.//#import "ViewController.h"@interface ViewController () <UIAlertViewDelegate>@property (weak, nonatomic) IBOutlet UILabel *counterLabel;@property (nonatomic,strong) NSTimer *timer;@end@implementation ViewController#pragma mark - 计时器的播放实现- (IBAction)start{    NSLog(@"%s",__FUNCTION__);    //间隔一秒更新counterLabel的显示    //计时器    //往运行循环添加timer的方式一:-------------------------------------------    /**     Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode.     参数说明     1》seconds: double 时间间隔     2》target: The object to which to send the message specified by aSelector when the timer fires. 监听时钟触发的对象     3》Selector: The message to send to target when the timer fires.调用的方法     The selector should have the following signature: timerFireMethod:     - (void)timerFireMethod:(NSTimer *)timer     4》userInfo:     The user info for the timer.通常为nil,可用于区分计时器     repeats:if YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires.是否重复     *///    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];    //将timer添加到运行循环的方式二-------------------------------------------    self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];    //Registers a given timer with a given input mode.NSRunLoopCommonModes (监听滚动模式)    [[NSRunLoop  currentRunLoop] addTimer:self.timer forMode: NSRunLoopCommonModes];}/** 时钟更新方法 */- (void) updateTimer:(NSTimer *) timer{    //1>取出标签的数字    int count = self.counterLabel.text.intValue;    //若counterLabel.text.intValue =0 ,弹出一些提示信息,否则进行倒计时    if (0 > --count) {//count-- 先赋值,再自减        [self pause];        [[[UIAlertView alloc]initWithTitle:@"start" message:@"In the beginning, laydia" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"done",@"kevin",nil] show];        return;    }    //2》修改counterLabel的text信息    self.counterLabel.text = [NSString stringWithFormat: @"%d",count];//--count 先自减,再赋值}- (IBAction)pause{    NSLog(@"%s",__FUNCTION__);    //停止时钟,一旦调用invalidate:方法,timer就失效,如果要重新启动时钟,需要重新实例化    [self.timer invalidate];//唯一停止时钟的方法}- (IBAction)clean{    NSLog(@"%s",__FUNCTION__);}#pragma mark - UIAlertViewDelegate 的协议方法- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{    NSLog(@"%lu",buttonIndex);}- (void)alertViewCancel:(UIAlertView *)alertView{    NSLog(@"%s",__FUNCTION__);}-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView{    NSLog(@"%s",__FUNCTION__);    return NO;}@end

图片轮播器

开发步骤:
1. scrollView getter方法懒加载
只指定了大小,添加到视图
2. viewDidLoad中添加图像,并且计算位置
3. 运行观察效果,修改scrollView的属性…….
4. 实例化UIPageControl
5. 因为分页控件和滚动视图是分离的,因此监听滚动停止代理方法,修改分页控件的页数
6. 将UIPageControl定义成属性,并且添加监听方法
7. 实现监听方法,页数变化后,修改scrollView的位置
8. 添加时钟,调用分页控件的监听方法,实现图片自动轮播

/  ViewController.m//  20160318-图片轮播器/** 今天的开发步骤: 1. scrollView getter方法懒加载 只指定了大小,添加到视图 2. viewDidLoad中添加图像,并且计算位置 3. 运行观察效果,修改scrollView的属性....... 4. 实例化UIPageControl 5. 因为分页控件和滚动视图是分离的,因此监听滚动停止代理方法,修改分页控件的页数 6. 将UIPageControl定义成属性,并且添加监听方法 7. 实现监听方法,页数变化后,修改scrollView的位置 8. 添加时钟,调用分页控件的监听方法,实现图片自动轮播 */////  Created by devzkn on 3/18/16.//  Copyright © 2016 hisun. All rights reserved.//#import "ViewController.h"#define kImageCount 5@interface ViewController () <UIScrollViewDelegate>@property (nonatomic,weak) UIScrollView *scrollView;@property (nonatomic,weak) UIPageControl *pageControl;@property (nonatomic,strong) NSTimer *timer;@end@implementation ViewController/** 重写getter方法,进行懒加载实例化属性对象 */- (UIPageControl *)pageControl{    if (nil == _pageControl) {        //实例化属性        UIPageControl *tmpPageControl = [[UIPageControl alloc]init];        //设置控件大小        CGSize size = [tmpPageControl sizeForNumberOfPages:kImageCount];        [tmpPageControl setBounds:CGRectMake(0, 0, size.width, size.height)];        //设置总页数        [tmpPageControl setNumberOfPages:kImageCount];        //设置颜色        [tmpPageControl setPageIndicatorTintColor:[UIColor redColor]];        [tmpPageControl setCurrentPageIndicatorTintColor:[UIColor blackColor]];        //设置位置        [tmpPageControl setCenter:CGPointMake(self.view.center.x, CGRectGetHeight(self.scrollView.bounds))];        _pageControl = tmpPageControl;        //添加监听方法:再oc中,继承于UIControl的控件,绝大多数都可以监听UIControlEventValueChanged事件,UIButton除外        [_pageControl addTarget:self action:@selector(changePage) forControlEvents:UIControlEventValueChanged];        [self.view addSubview:_pageControl];    }    return _pageControl;}/** 重写getter方法,进行懒加载方式实例化属性 */- (UIScrollView *)scrollView{    if (nil == _scrollView) {        UIScrollView *tmpScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(10, 20, 300, 130)];        _scrollView = tmpScrollView;        //代理设置、contentSize、contentOffset、contentInset        [_scrollView setDelegate:self];        [_scrollView setContentSize:CGSizeMake(CGRectGetWidth(_scrollView.bounds)*kImageCount, 0)];        //设置分页        [_scrollView setPagingEnabled:YES];        //取消水平滚动条        [_scrollView setShowsHorizontalScrollIndicator:NO];        [_scrollView setShowsVerticalScrollIndicator:NO];        //取消弹簧效果        [_scrollView setBounces:NO];        [_scrollView setBackgroundColor:[UIColor lightGrayColor]];        [self.view addSubview:_scrollView];    }    return _scrollView;}/** 通常用来设置数据 */- (void)viewDidLoad {    [super viewDidLoad];    //设置图片(内容)    for (int i=0; i<kImageCount; i++) {         NSString *imageName = [NSString stringWithFormat:@"img_%02d",i+1];        UIImage *image = [UIImage imageNamed:imageName] ;        UIImageView *imageView = [[UIImageView alloc]initWithFrame:self.scrollView.bounds];        [imageView setImage:image];        [self.scrollView addSubview:imageView];    }    //计算imageView的位置    [[self.scrollView subviews] enumerateObjectsUsingBlock:^(UIImageView *imageView, NSUInteger idx, BOOL *stop) {        CGRect frame =imageView.frame;        frame.origin.x = idx*CGRectGetWidth(frame);        [imageView setFrame:frame];    }];    [self.pageControl setCurrentPage:0];    //启动时钟    [self startTimer];}- (void) startTimer{    //启动时钟(修改UIPageControl 的currentPage 同时也修改UIScrollView 的contentOffset)    self.timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(photoCarousel:) userInfo:nil repeats:YES];    //注册时钟到runloop    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];}/** 修改scrollView的contentoffset的同时,对UIPageControl进行页码设置,来实现定时图片轮播 */- (void) photoCarousel:(NSTimer *)timer{    //设置页码    [self.pageControl setCurrentPage:((self.pageControl.currentPage+1)%kImageCount)];    //设置偏移位置//    [self.scrollView setContentOffset:CGPointMake(self.pageControl.currentPage*CGRectGetWidth(self.scrollView.bounds), 0) animated:YES];    [self changePage];}#pragma mark scrollView 的代理方法/** Tells the delegate that the scroll view has ended decelerating the scrolling movement. */- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{    //更新pageControl的页码//    UIPageControl *pageControl =[[self.view subviews]lastObject];    self.pageControl.currentPage= scrollView.contentOffset.x/ CGRectGetWidth(scrollView.bounds);}//抓住图片时,停止时钟- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{    [self.timer invalidate];    NSLog(@"%s",__FUNCTION__);}// 停止抓住图片时,开启时钟- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{    [self startTimer];    NSLog(@"%s",__FUNCTION__);}/** 切换图片(修改UIScrollView 显示的UIImageView对象,即修改contentOffSize即可 ) */- (void) changePage{//根据pageControl的页码,来调整UIScrollView的内容(图像)位置    CGFloat x= self.pageControl.currentPage*CGRectGetWidth(self.scrollView.frame);    [self.scrollView setContentOffset:CGPointMake(x, 0) animated:YES];}@end

总结: