UIActivityIndicator and GCD/Threading - objective-c

i am fetching a list of photos from a server and displaying them. i'm using GCD to thread the server calls. I got it working, but i want to add in a UIActivityIndicator for each UIImageView to show that its doing something and will appear.
i'm not sure what the best method would be.
code:
UIScrollView *myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, photoView.frame.size.height)];
myScrollView.backgroundColor = [UIColor whiteColor];
myScrollView.pagingEnabled = TRUE;
myScrollView.scrollEnabled = TRUE;
myScrollView.frame = CGRectMake(myScrollView.frame.origin.x, myScrollView.frame.origin.y, (6 * THUMBNAIL_SIZE) + (PHOTO_VIEWER_OFFSET_COLUM_1 * 2), myScrollView.frame.size.height);
//get list of photos
for (int i = 0; i < 6; i++)
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(#"async thread %#", [NSThread currentThread]);
//retrieveThumbnailedGeotaggedPhotoWithPhotoID will make a server call
MyUIImageView *myImageView = [[MyUIImageView alloc] initWithImage:[self retrieveThumbnailedGeoTaggedPhotoWithPhotoID:#"test"]];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(#"main thread %#", [NSThread currentThread]);
myImageView.frame = CGRectMake(myImageView.frame.origin.x, myImageView.frame.origin.y, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
myImageView.backgroundColor = [UIColor clearColor];
myImageView.position = i;
myImageView.isEnlarged = FALSE;
myImageView.delegate = self;
int group = (i / 6);
myImageView.frame = CGRectMake((i * myImageView.frame.size.width) + (PHOTO_VIEWER_OFFSET_COLUM_1 * ((group * 2) + 1)),
PHOTO_VIEWER_OFFSET_COLUM_1,
myImageView.frame.size.width,
myImageView.frame.size.height);
myScrollView.contentSize = CGSizeMake((myScrollView.frame.size.width * (group + 1)), myScrollView.contentSize.height);
[myScrollView addSubview:myImageView];
});
});
}
i'm pretty sure animating and stopping the activityIndicator needs to be on the main thread, but not sure how to include it. it needs to be animating during the "retrieveThumbnailedGeoTaggedPhotoWithPhotoID" method which is in a thread (but not main thread).

k, i re-ordered it:
for (int i = 0; i < 8; i++)
{
//create the subviews first
MyUIImageView *myImageView = [[MyUIImageView alloc] initWithFrame:CGRectMake((i * THUMBNAIL_SIZE) + (PHOTO_VIEWER_OFFSET_COLUM_1 * (((i / 6) * 2) + 1)),
PHOTO_VIEWER_OFFSET_COLUM_1,
THUMBNAIL_SIZE,
THUMBNAIL_SIZE)];
myImageView.backgroundColor = [UIColor whiteColor];
[myScrollView addSubview:myImageView];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.center = CGPointMake(THUMBNAIL_SIZE / 2, THUMBNAIL_SIZE / 2);
[myImageView addSubview:spinner];
[spinner startAnimating];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
UIImage *myImage = [[UIImage alloc] init];
//only make the server call in the async queue
myImage = [self retrieveThumbnailedGeoTaggedPhotoWithPhotoID:#"test"];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(#"main thread %#", [NSThread currentThread]);
//MyUIImageView *myImageView = [[MyUIImageView alloc] initWithImage:myImage];
[myImageView setImage:myImage];
myImageView.frame = CGRectMake(myImageView.frame.origin.x, myImageView.frame.origin.y, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
myImageView.backgroundColor = [UIColor clearColor];
myImageView.position = i;
myImageView.isEnlarged = FALSE;
myImageView.delegate = self;
int group = (i / 6);
myImageView.frame = CGRectMake((i * myImageView.frame.size.width) + (PHOTO_VIEWER_OFFSET_COLUM_1 * ((group * 2) + 1)),
PHOTO_VIEWER_OFFSET_COLUM_1,
myImageView.frame.size.width,
myImageView.frame.size.height);
myScrollView.contentSize = CGSizeMake((myScrollView.frame.size.width * (group + 1)), myScrollView.contentSize.height);
[spinner stopAnimating];
});
});
}

Related

Image not centered vertically in scrollview

What am I missing? The inner scrollview and the image view fill the entire screen. But somehow my image is not centered. The top left corner of the image starts in the center of the view, but I would like to have the image nicely centered. Also during zooming.
-(void)prepareScrollView
{
for(int i =0;i<[self.layoverPhotoAssets count];i++){
PHAsset *asset = self.layoverPhotoAssets[i];
FMImageZoomViewController *zoomController = [[FMImageZoomViewController alloc] init];
// UIImageView *imageView = [[UIImageView alloc] init];
int x = self.scrollView.frame.size.width * i;
zoomController.view.frame = CGRectMake(x, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
//zoomController.view.frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
[self.scrollView addSubview:zoomController.view];
zoomController.zoomScroller.delegate = self;
zoomController.imageView.tag = 1;
[self.zoomControllers addObject:zoomController];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeFast;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; //I only want the highest possible quality
options.synchronous = NO;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:zoomController.zoomScroller.frame.size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if(result){
zoomController.imageView.image = result;
zoomController.imageView.backgroundColor = [UIColor redColor];
}
});
}];
//self.scrollView.contentSize= ;
}
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * [self.layoverPhotoAssets count], 0)];
[self scrollToAsset:self.selectedAsset];
}
Consider:
zoomController.view.frame = CGRectMake(x, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
[self.scrollView addSubview:zoomController.view];
That cannot be right. If zoomController.view is to be a subview of self.scrollView, its frame within self.scrollView is in terms of the bounds of self.scrollView, not the frame of self.scrollView.
Solved it like this:
-(void)prepareScrollView
{
for(int i =0;i<[self.layoverPhotoAssets count];i++){
PHAsset *asset = self.layoverPhotoAssets[i];
FMImageZoomViewController *zoomController = [[FMImageZoomViewController alloc] init];
// UIImageView *imageView = [[UIImageView alloc] init];
int x = self.scrollView.frame.size.width * i;
zoomController.view.frame = CGRectMake(x, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
//zoomController.view.frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
[self.scrollView addSubview:zoomController.view];
zoomController.zoomScroller.delegate = self;
[self.zoomControllers addObject:zoomController];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeExact;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; //I only want the highest possible quality
options.synchronous = NO;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:zoomController.zoomScroller.bounds.size contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if(result){
zoomController.imageView = [[UIImageView alloc] initWithImage:result];
zoomController.imageView.frame = zoomController.zoomScroller.bounds;
[zoomController.imageView setContentMode:UIViewContentModeScaleAspectFit];
zoomController.imageView.clipsToBounds = YES;
[zoomController.imageView setCenter: self.scrollView.center];
zoomController.imageView.tag = 1;
[zoomController.zoomScroller addSubview:zoomController.imageView];
// zoomController.imageView.contentMode = UIViewContentModeCenter;
// if (zoomController.imageView.bounds.size.width > result.size.width && zoomController.imageView.bounds.size.height > result.size.height) {
// zoomController.imageView.contentMode = UIViewContentModeScaleAspectFit;
// }
}
});
}];
//self.scrollView.contentSize= ;
}
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * [self.layoverPhotoAssets count], 0)];
[self scrollToAsset:self.selectedAsset];
}

UIScrollView with pageable image gallery - Any memory problems? And what about zooming?

I want to have a similar functionality as in the Photos app on the iPhone in my Scrollview. So I've added all images to my scrollview like this and it works nicely.
-(void)prepareScrollView
{
for(int i =0;i<[self.layoverPhotoAssets count];i++){
PHAsset *asset = self.layoverPhotoAssets[i];
UIImageView *imageView = [[UIImageView alloc] init];
int x = self.scrollView.frame.size.width * i;
imageView.frame = CGRectMake(x, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height);
imageView.contentMode = UIViewContentModeScaleAspectFit;
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeFast;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; //I only want the highest possible quality
options.synchronous = NO;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:self.scrollView.frame.size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if(result){
imageView.image = result;
}
});
}];
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width * (i + 1), self.scrollView.frame.size.height)];
//self.scrollView.contentSize= ;
[self.scrollView addSubview:imageView];
}
}
However I have 2 questions:
1. Like this, all images will be loaded at once. Memory wise this is quite bad. How can I improve that without worsening the user experience?
2. How can I make the image itself zoomable?

GCD Scrollview loading issue

I'm using GCD to load images for my scroll view but rather than following the frames i created it makes only a single frame in which the images just flicker through. Here's my code:
//Create the array
-(void)awakeFromNib {
images = [NSMutableArray arrayWithObjects: [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"imageOne" ofType:#"png"]], [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"imageTwo" ofType:#"png"]], [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"imageThree" ofType:#"png"]],nil];
}
//Populate scrollview
-(void)populate {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
scrollview.pagingEnabled = YES;
scrollview.backgroundColor = [UIColor clearColor];
scrollview.clipsToBounds = YES;
scrollview.delegate = self;
[scrollview setContentSize:CGSizeMake(2 * scrollview.frame.size.width, scrollview.frame.size.height)];
int number = [images count] ;
NSLog(#"%i",images);
int rowTwoInt = 0;
int rowThreeInt = 0;
int rowFourInt = 0;
for (int i = 0; i < number; i++) {
if (i <= 3) {
finalFrame = CGRectMake( i*(80), 12, 80, 80);
}
if (i == 4) {
finalFrame = CGRectMake(0, 95, 80, 80);
}
if ((i >4) && (i <= 7)) {
rowTwoInt = rowTwoInt + 80;
finalFrame = CGRectMake(rowTwoInt, 95, 80, 80);
}
if (i == 8) {
finalFrame = CGRectMake(0, 178, 80, 80);
}
if ((i > 8) && (i <= 11)) {
rowThreeInt = rowThreeInt + 80;
finalFrame = CGRectMake(rowThreeInt, 178, 80, 80);
}
if (i == 12) {
finalFrame = CGRectMake(0, 261, 80, 80);
}
if ((i > 12) && (i <= 15)) {
rowFourInt = rowFourInt + 80;
finalFrame = CGRectMake(rowFourInt, 261, 80, 80);
}
IconButton = [UIButton buttonWithType:UIButtonTypeCustom];
IconButton.frame = CGRectMake(0, 0, 57, 57);
IconButton.center = CGPointMake(40, 29);
[IconButton addTarget:self action:#selector(Selected:) forControlEvents:UIControlEventTouchUpInside];
IconButton.tag = i;
dispatch_async(queue, ^{
UIImage *icon = [images objectAtIndex:i];
dispatch_sync(dispatch_get_main_queue(), ^{
[IconButton setImage:icon forState:UIControlStateNormal];
});
});
[cell addSubview:IconButton];
cell = [[UIView alloc] initWithFrame:finalFrame];
[scrollview addSubview:cell];
So what am i doing wrong? I'm new with GCD so it's probably something with that. Also if you see a way to improve UIScrollView performance, please let me know.
I suspect you have declared IconButton as an instance variable, a static variable, or a global variable.
Each time through your loop, you change the value of IconButton. By the time your twelve queue blocks execute, IconButton is set to its final value - a reference to the last button you created. All the blocks use the instance (or static or global) IconButton variable, so all the blocks update the same, final button.
Make a local variable to reference the button, and use that local variable in the loop:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
IconButton = button;
IconButton.frame = CGRectMake(0, 0, 57, 57);
...
dispatch_async(queue, ^{
UIImage *icon = [images objectAtIndex:i];
dispatch_sync(dispatch_get_main_queue(), ^{
[button setImage:icon forState:UIControlStateNormal];
});
});
Each block will capture the value of the local variable at the moment the block is created, so each block will capture a reference to a different button.

Setting UIButton Image Using AFNetworking

I have this code in my project that creates UIButtons with labels and images with values coming from a web service.
- (void)getMoviePosterImages
{
for (int i = 0; i < [self.rowCount intValue]; i++)
{
NSArray *postersArray = [self.jsonMutableArray objectAtIndex:i];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[postersArray objectAtIndex:6]]] imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image)
{
[moviePosterButton setBackgroundImage:image forState:UIControlStateNormal];
}
failure:nil];
[operation start];
}
}
Here's the code where I created the UILabels:
- (void)displayMovieTitlesAndFrames
{
int imageCount = [self.rowCount intValue];
int offset_x = 21;
int offset_y = 24;
for (int i = 0; i < imageCount; i++)
{
// compute x & y offset
if (i % 3 == 0)
{
offset_x = 21;
}
else if (i % 3 == 1)
{
offset_x = 115;
}
else
{
offset_x = 210;
}
whiteBackgroundLabel = [[[UILabel alloc] initWithFrame:CGRectMake(offset_x, offset_y, MOVIE_THUMBNAIL_W, MOVIE_THUMBNAIL_H)] autorelease];
whiteBackgroundLabel.backgroundColor = [UIColor whiteColor];
whiteBackgroundLabel.layer.cornerRadius = 3.0;
whiteBackgroundLabel.layer.borderColor = [[UIColor lightGrayColor] CGColor];
whiteBackgroundLabel.layer.borderWidth = 1.0;
[scrollview addSubview:whiteBackgroundLabel];
moviePosterButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
moviePosterButton.frame = CGRectMake(offset_x + 5, offset_y + 5, MOVIE_THUMBNAIL_W - 10, MOVIE_THUMBNAIL_H - 10);
moviePosterButton.backgroundColor = [UIColor clearColor];
[moviePosterButton setBackgroundImage:[UIImage imageNamed:#"placeholder.png"] forState:UIControlStateNormal];
moviePosterButton.tag = i;
[moviePosterButton addTarget:self
action:#selector(imageButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[scrollview addSubview:moviePosterButton];
movieTitleLabel = [[[UILabel alloc] initWithFrame:CGRectMake(offset_x, offset_y + 143, 90, 20)] autorelease];
movieTitleLabel.backgroundColor = [UIColor whiteColor];
movieTitleLabel.layer.cornerRadius = 3.0;
movieTitleLabel.layer.borderColor = [[UIColor lightGrayColor] CGColor];
movieTitleLabel.layer.borderWidth = 1.0;
movieTitleLabel.font = [UIFont fontWithName:#"Helvetica" size:11.0];
movieTitleLabel.textColor = [UIColor darkGrayColor];
movieTitleLabel.textAlignment = UITextAlignmentCenter;
movieTitleLabel.numberOfLines = 1;
movieTitleLabel.text = [[self.jsonMutableArray objectAtIndex:i] objectAtIndex:1];
[scrollview addSubview:movieTitleLabel];
quickBuyButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
quickBuyButton.frame = CGRectMake(offset_x + 1 + (MOVIE_THUMBNAIL_W - QUICK_BUY_BUTTON_W - 2), offset_y - 1 + 2, QUICK_BUY_BUTTON_W, QUICK_BUY_BUTTON_H);
quickBuyButton.backgroundColor = [UIColor clearColor];
[quickBuyButton setBackgroundImage:QUICK_BUY_BUTTON forState:UIControlStateNormal];
quickBuyButton.tag = i;
[quickBuyButton addTarget:self
action:#selector(quickBuyButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[scrollview addSubview:quickBuyButton];
// increment offset
if (offset_x == 210)
{
offset_y += 171;
}
}
if ((offset_x == 21) || (offset_x == 115))
{
offset_y += 171;
}
[self adjustScrollViewAndBackground:offset_y];
}
All my UIButtons are created with their respective tags and I want to put their images on each on those buttons. The code above works only on the last UIButton created. I want to populate all of my buttons with images using the code above. Can someone tell me where I'm getting it all wrong?
In your getMoviePosterImages method you are setting an image to the moviePosterButton which might be the last button you just created so this is normal if only the last button gets its image. You need either to retrieve each buttons by their tags or build an array with all you buttons so you can easily access them. You could maybe do something like that:
- (void)getMoviePosterImages
{
for (int i = 0; i < [self.rowCount intValue]; i++)
{
NSArray *postersArray = [self.jsonMutableArray objectAtIndex:i];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[postersArray objectAtIndex:6]]] imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image)
{
[(UIButton *)buttonsArray[i] setBackgroundImage:image forState:UIControlStateNormal];
// or
// [(UIButton *)[self.view viewWithTag:i] setBackgroundImage:image forState:UIControlStateNormal];
}
failure:nil];
[operation start];
}
}
Hope this helps ;)

UIScrollView and UIPageControl, what am I doing wrong?

I have a class which is predefining some labels and binding their values in a UIScrollView.
I've managed to show those labels, but now I'm stuck at putting a label at the 2nd part of the ScrollView.
I've pushed my project to gitHub.
I can change the label's place on the already visible part, but I must be overlooking something.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = _detail.name;
UIColor *bgColor = [UIColor blackColor];
UIColor *txtColor = [UIColor grayColor];
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size.width = _scrollView.frame.size.width *2;
NSString *phoneNr = (_detail.phoneNr == nil) ? #"Not specified" : _detail.phoneNr;
_telLabel = [self prepareLabel:phoneNr textColor:txtColor bgColor:bgColor page:0 y:telNrYAxis];
_webLabel = [self prepareLabel:#"Visit website" textColor:txtColor bgColor:bgColor page:0 y:websiteYAxis];
_detail.address = [_detail.address stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"\n\t "]];
NSArray *addressArrComponents = [_detail.address componentsSeparatedByString:#","] ;
_addressLabel = [self prepareLabel:[addressArrComponents componentsJoinedByString:#"\n"] textColor:txtColor bgColor:bgColor page:0 y:addressYAxis];
UILabel *lbl = [self prepareLabel:#"Derp" textColor:txtColor bgColor:bgColor page:1 y:0];
_detailView = [[UIView alloc] initWithFrame:frame];
_detailView.backgroundColor = [UIColor blackColor];
[_detailView addSubview:_webLabel];
[_detailView addSubview:_addressLabel];
[_detailView addSubview:_telLabel];
[_detailView addSubview:lbl];
[_scrollView addSubview:_detailView];
NSLog(#"%f",self.view.frame.size.height - (_scrollView.frame.origin.y + _scrollView.frame.size.height) );
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height - 250 , self.view.frame.size.width/4, 120)];
_pageControl.numberOfPages=2;
_pageControl.currentPage=0;
[_pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventTouchDown];
_scrollView.contentSize = CGSizeMake(800,800);
_scrollView.delegate=self;
_scrollView.backgroundColor = [UIColor blackColor];
_scrollView.pagingEnabled=YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
[self pageChange:0];
[self.view addSubview:_pageControl];
// Do any additional setup after loading the view.
}
-(UILabel*)prepareLabel:(NSString*) text textColor:(UIColor*)textColor bgColor:(UIColor*)backgroundColor page:(int)page y:(int) yPos{
int lines = [[text componentsSeparatedByString:#"\n"] count];
CGRect labelFrame = CGRectMake(_detailView.frame.size.width * page +20,yPos,self.view.frame.size.width, [UIFont systemFontSize]*lines);
UILabel *returnLabel = [[UILabel alloc] initWithFrame:labelFrame];
returnLabel.text = text;
returnLabel.backgroundColor = backgroundColor;
returnLabel.textColor = textColor;
[returnLabel setNumberOfLines:lines];
[returnLabel sizeToFit];
return returnLabel;
}
- (void)loadScrollViewWithPage:(int)page {
NSLog(#"Derped");
}
-(IBAction)pageChange:(id)sender{
int page=_pageControl.currentPage;
CGRect frame = _scrollView.frame;
frame.origin.x = _scrollView.frame.size.width * page;
frame.origin.y = 0;
//CGRect frame= (page == 0) ? _detailFrame : _reviewFrame;
NSLog(#"%f",frame.origin.x);
[_scrollView scrollRectToVisible:frame animated:YES];
}
The delegate -(IBAction)pageChange:(id)sender gets fired, but I must be doing something wrong with the frames somewhere :s
Please take a look!
Try to implement this method may help you :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = self.scrollView.frame.size.width;
float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
self.pageControl.currentPage = page;
}