I have a slide display that gathers a series of images from a database. Each image has descriptions and other properties associated with it. Basically I want to update the text of a UILabel every time a new image is loaded. How can I do that?
Here is what I am working with:
//SLIDE MENU
- (void)loadVisiblePages {
// First, determine which page is currently visible
CGFloat pageWidth = gridView.frame.size.width;
NSInteger page = (NSInteger)floor((gridView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
//NSArray * descriptArray[20];
// Update the page control
pageControl.currentPage = page;
// Work out which pages you want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
// descriptArray[i] = selectedPhotoDesc;
}
for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (void)loadPage:(NSInteger)page {
NSURL* imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#%#/%#.jpg", host, photoPath, collection, photoNumber]];
//get photo from server
NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
UIImage *image = [[UIImage alloc] initWithData: imageData];
if (page < 0 || page >= 20) {
return;
}
// Load an individual page, first checking if you've already loaded it
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView == [NSNull null]) {
CGRect frame = gridView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
frame = CGRectInset(frame, 10.0f, 0.0f);
UIImageView *newPageView = [[UIImageView alloc] initWithImage:image];
newPageView.frame = frame;
[gridView addSubview:newPageView];
labelDescription.text = descriptionArray[page];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what you have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
labelDescription.text = #"";
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// Load the pages that are now on screen
[self loadVisiblePages];
}
I should mention that I am able to slide different images but cannot update their text. As it stands, I can only get the text corresponding to the first image but nothing else.
THANKS
Related
I have an NSMutableArray with some UIImageView's inside. After a scroll action I want to change the images of some UIImageView but I can't.
This is how I first initiate the Array:
NSMutableArray *dotsImageSliderList = [[NSMutableArray alloc]init];
for (int i=0; i<totalImages; i++)
{
UIImageView *dot =[[UIImageView alloc] initWithFrame:CGRectMake(distance,2,5,5)];
if (i==0)
{
dot.image=[UIImage imageNamed:#"dotselected.png"];
}
else
{
dot.image=[UIImage imageNamed:#"dotunselected.png"];
}
[dotsImageSliderList addObject:dot];
}
And this is how I retrieve the UIImageView's and trying to change the images:
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSInteger pagenumber = scrollView.contentOffset.x / scrollView.bounds.size.width;
NSLog(#"%zd", pagenumber);
if (pagenumber < [dotsImageSliderList count])
{
for (int i=0; i<[dotsImageSliderList count]; i++)
{
UIImageView *view = [dotsImageSliderList objectAtIndex:pagenumber];
if (i==pagenumber)
{
view.image=[UIImage imageNamed:#"dotselected.png"];
}
else
{
view.image=[UIImage imageNamed:#"dotunselected.png"];
}
}
}
}
I have no idea why the images don't change. Can you spot the mistake?
Initialise image object outside the loop.
NSMutableArray *dotsImageSliderList = [[NSMutableArray alloc]init];
UIImage * selectedImage = [UIImage imageNamed:#"dotselected.png"];
UIImage * unselectedImage = [UIImage imageNamed:#"dotunselected.png"];
for (int i=0; i<totalImages; i++)
{
UIImageView *dot =[[UIImageView alloc] initWithFrame:CGRectMake(distance,2,5,5)];
if (i==0)
{
dot.image=selectedImage;
}
else
{
dot.image=unselectedImage;
}
[dotsImageSliderList addObject:dot];
}
Super silly mistake. I have to change this line:
UIImageView *view = [dotsImageSliderList objectAtIndex:pagenumber];
to this:
UIImageView *view = [dotsImageSliderList objectAtIndex:i];
in my project, I have a UITableView view which if I click on the cell it will go to the detail page. In detail page it has a UIScrollView that display an images.
The problem that I'm facing is images from url did not display. It only display placeholder image. But after I click it back to the UITableView view and click on the same cell again. It will display the images from URL.
Here is my code
- (void)loadVisiblePages {
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
// Update the page control
self.pageControl.currentPage = page;
// Work out which pages you want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
// Load pages in our range
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
// Purge anything after the last page
for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what you have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
- (void)loadPage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what you have to display, then do nothing
return;
}
// 1
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView == [NSNull null]) {
// 2
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
self.scrollView.pagingEnabled = YES;
// 3
UIImageView *newPageView = [[UIImageView alloc] initWithImage:[self.pageImages objectAtIndex:page]];
//Fit the Screen
//newPageView.contentMode = UIViewContentModeScaleToFill;
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
newPageView.userInteractionEnabled = YES;
[self.scrollView addSubview:newPageView];
// 4
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
UITapGestureRecognizer *SingleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(actionHandleTapOnImageView:)];
[SingleTap setNumberOfTapsRequired:1];
[newPageView addGestureRecognizer:SingleTap];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// Load the pages that are now on screen
[self loadVisiblePages];
}
- (void)viewDidLoad {
[super viewDidLoad]
// Add image into slide image
if([data.gallery count] == 1){
_imageView1 = [[UIImageView alloc] init];
[_imageView1 sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", data.gallery[0]]]placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
self.pageImages = [[NSMutableArray alloc] initWithObjects:_imageView1.image, nil];
}else if([data.gallery count] == 2){
// Load image from server
_imageView1 = [[UIImageView alloc] init];
[_imageView1 sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", data.gallery[0]]]placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
self.pageImages = [[NSMutableArray alloc] initWithObjects:_imageView1.image, nil];
_imageView2 = [[UIImageView alloc] init];
[_imageView2 sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", data.gallery[1]]]placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
// Add image to page
self.pageImages = [[NSMutableArray alloc] initWithObjects:_imageView1.image,_imageView2.image, nil];
}
}
NSInteger pageCount = self.pageImages.count;
// 2
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
// 3
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 4
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
// 5
[self loadVisiblePages];
}
Hi I am building an app in which I want my contents to be displayed on a view which is horizontally scroll-able.
I have implemented the following code for it:
-(void)DownLoadData:(NSString *)indexSelect
{
self._parserForNewsDetail = [afaqsParser getInstance];
[[afaqsParser getInstance] setCacheNeed:TRUE];
[self._parserForNewsDetail parseWithUrl:[_arrUrlLinks objectAtIndex:[indexSelect integerValue]] UrlTypefor:nil];
NSDictionary *resultDic;
resultDic = [[[self._parserForNewsDetail getLinkAndIdDic] valueForKey:#"items"]objectAtIndex:0];
NSLog(#"Detail Dic = %#",[resultDic description]);
if (resultDic== NULL || resultDic ==nil)
{
//Check internet here
[[SharedUtilities getInstance]RemoveActivityIndicatorView];
[SharedUtilities ShowAlert:#"No Data Found" title:nil withView:self.view];
return;
}
[self performSelectorOnMainThread:#selector(SetValuesInUserInterface:) withObject: resultDic waitUntilDone:NO];
[[SharedUtilities getInstance]RemoveActivityIndicatorView];
}
-(void)DownloadNext:(NSString *)indexSelect
{
resultDic = [[[self._parserForNewsDetail getLinkAndIdDic] valueForKey:#"items"]objectAtIndex:0];
NSURL *imgurl =[NSURL URLWithString:[[Dic valueForKey:#"image"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSArray *subviewsArr = [self.view subviews];
for (int i=0; i<[subviewsArr count]; i++) {
if ([[subviewsArr objectAtIndex:i] isKindOfClass:[ImageDownLoader class]]) {
}
}
[self loadScrollView];
}
-(void)SetValuesInUserInterface:(NSDictionary *)Dic
{
self._imageView1.layer.cornerRadius = 4;
self._imageView1.clipsToBounds = YES;
self._imageView1.tag = 999;
NSURL *imgurl =[NSURL URLWithString:[[Dic valueForKey:#"image"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
self._imageView1.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:imgurl]];
NSArray *subviewsArr = [self.view subviews];
for (int i=0; i<[subviewsArr count]; i++) {
if ([[subviewsArr objectAtIndex:i] isKindOfClass:[ImageDownLoader class]]) {
[[subviewsArr objectAtIndex:i] removeFromSuperview];
}
}
if ([[Dic valueForKey:#"image"] isEqual:#""])
{
_imageView1.hidden=YES;
_txtView.frame=CGRectMake(4.0f,95.0f,_txtView.frame.size.width,_txtView.frame.size.height );
NSLog(#"NO IMAGE");
}
else{
_imageView1.hidden=NO;
_imageView1.frame=CGRectMake(4.0f,95.0f,310.0f,180.0f );
// _txtView.frame=CGRectMake(4.0f,316.0f,310.0f,159.0f );
_txtView.frame=CGRectMake(4.0f,316.0f,_txtView.frame.size.width,_txtView.frame.size.height );
NSLog(#"IMAGE VISIBLE");
}
self._scrollView.scrollEnabled = YES;
self._scrollView.showsVerticalScrollIndicator = YES;
self._scrollView.showsHorizontalScrollIndicator = YES;
self._header.font = [UIFont fontWithName:#"HelveticaNeue-MediumCond" size:18];
[self._header setText: [Dic valueForKey:#"header"]];
self._header.textColor=[UIColor blackColor];
[self._Writer setText:[Dic valueForKey:#"AUTHOR"]];
[self._kicker setText:[Dic valueForKey:#"kicker"]];
[self._txtView setText:[Dic valueForKey:#"ARTICLE_BODY"]];
NSString *writer;
if ([[Dic valueForKey:#"AUTHOR"] length]>2)
{
writer=[NSString stringWithFormat:#"%#, ",[Dic valueForKey:#"AUTHOR"]];
}
else
{
writer=#"";
}
[self._Writer setText:str];
[_txtView sizeToFit]; //added
[_txtView layoutIfNeeded]; //added
CGRect frame = self._txtView.frame;
self._txtView.frame = frame;
[_txtView setScrollEnabled:NO];
self._scrollView.contentSize = CGSizeMake(320,440+frame.size.height);
_titleLabel.frame= CGRectMake(0, self._scrollView.contentSize.height-119, [[UIScreen mainScreen] bounds].size.width, 40);
_titleLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:1];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.font = [UIFont fontWithName:#"Helvetica" size:13.5];
_titleLabel.numberOfLines=2;
[self._scrollView addSubview:_titleLabel];
[self loadScrollView];
}
-(void)viewWillAppear:(BOOL)animated
{
self.navigationController.navigationBarHidden = YES;
}
- (void)viewDidLoad
{
[self DownLoadData:resultDic];
UISwipeGestureRecognizer *rightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(loadScrollView)];
rightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[rightRecognizer setNumberOfTouchesRequired:1];
//add the your gestureRecognizer , where to detect the touch..
[_scrollView addGestureRecognizer:rightRecognizer];
UISwipeGestureRecognizer *leftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(loadScrollView)];
leftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[leftRecognizer setNumberOfTouchesRequired:1];
[_scrollView addGestureRecognizer:leftRecognizer];
}
- (void)rightSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer
{
[self btnPreviousClick];
[self loadScrollView];
}
- (void)leftSwipeHandle:(UISwipeGestureRecognizer*)gestureRecognizer
{
NSLog(#"leftSwipeHandle");
[self btnNextClick];
[self loadScrollView];
}
-(IBAction)btnNextClick
{
btnPreviousNews.userInteractionEnabled=TRUE;
if(count!=[_arrUrlLinks count] -1)
{
if(count==[_arrUrlLinks count]-2)
{
btnNextNews.userInteractionEnabled=FALSE;
[btnNextNews setImage:[UIImage imageNamed:#"arrow2_next.png"] forState:UIControlStateNormal];
}
[btnPreviousNews setImage:[UIImage imageNamed:#"arrow1_prev.png"] forState:UIControlStateNormal];
count=count +1;
_lblNewsCount.text=[NSString stringWithFormat:#"%d/%d",count+1,[_arrUrlLinks count]];
NSLog(#"next %d",count);
[self performSelectorInBackground:#selector(DownLoadData:) withObject:[NSString stringWithFormat:#"%d",count]];
}
else{
btnNextNews.userInteractionEnabled=FALSE;
}
}
-(void)btnPreviousClick
{
btnNextNews.userInteractionEnabled=TRUE;
if(count==0)
{
btnPreviousNews.userInteractionEnabled=FALSE;
}
else{
if(count==1)
{
[btnPreviousNews setImage:[UIImage imageNamed:#"arrow2_prev.png"] forState:UIControlStateNormal];
btnPreviousNews.userInteractionEnabled=FALSE;
}
[btnNextNews setImage:[UIImage imageNamed:#"arrow1_next.png"] forState:UIControlStateNormal];
count=count-1;
_lblNewsCount.text=[NSString stringWithFormat:#"%d/%d",count+1,[_arrUrlLinks count]];
NSLog(#"previous %d",count);
[self performSelectorInBackground:#selector(DownLoadData:) withObject:[NSString stringWithFormat:#"%d",count]];
}
}
-(void)loadScrollView
{
_scrollView.contentSize = CGSizeMake(0, _scrollView.frame.size.height);
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < [_arrUrlLinks count]; i++) {
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
count=1;
// a page is the width of the scroll view
_scrollView.pagingEnabled = YES;
_scrollView.contentSize = CGSizeMake(_scrollView.frame.size.width * [_arrUrlLinks count], _scrollView.frame.size.height);
_scrollView.showsHorizontalScrollIndicator =YES;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
_scrollView.delegate = self;
pageControl.numberOfPages = [_arrUrlLinks count];
pageControl.currentPage = 0;
[_scrollView addSubview:_txtView];
[_txtView setText:[Dic valueForKey:#"ARTICLE_BODY"]];
[controller.view addSubview:_txtView];
// pages are created on demand
// load the visible page
// load the page on either side to avoid flashes when the user starts scrolling
[self loadScrollViewWithPage:0];
[self loadScrollViewWithPage:1];
}
- (void)loadScrollViewWithPage:(int)page {
if (page < 0) return;
if (page >= [_arrUrlLinks count])
return;
// replace the placeholder if necessary
controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null]) {
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:#"iPhone"])
{
controller = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
}
else{
controller = [[MyViewController alloc] initWithNibName:#"MyViewController_ipad" bundle:nil];
}
[controller initWithPageNumber:page];
// [controller.view addSubview:_txtView];
// [controller.view addSubview:_imageview];
NSLog(#"loadscrollviewwithpage");
[viewControllers replaceObjectAtIndex:page withObject:controller];
// [controller release];
}
// add the controller's view to the scroll view
if (nil == controller.view.superview) {
CGRect frame = _scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
// _txtView.frame=frame;
// _imageview.frame=frame;
// _txtView.frame=CGRectMake(4.0f,316.0f,310.0f,159.0f );
_txtView=#"hello";
// [controller.view addSubview:_txtView];
[_imageView1 addSubview:controller.view];
// [_txtView addSubview:controller.view];
// [scrollView addSubview:controller.view];
NSLog(#"loadscrollviewwithpage................>>>>>>>>>>>>");
// [self._header setText: [Dic valueForKey:#"header"]];
// [self DownLoadData:resultDic];
//[self SetValuesInUserInterface:Dic];
[self DownloadNext:resultDic];
}
}
- (void)unloadScrollViewWithPage:(int)page {
if (page < 0) return;
if (page >= [_arrUrlLinks count]) return;
controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller != [NSNull null]) {
if (nil != controller.view.superview)
[controller.view removeFromSuperview];
[viewControllers replaceObjectAtIndex:page withObject:[NSNull null]];
// [controller.view addSubview:_txtView];
// [controller.view addSubview:_imageview];
NSLog(#"Unloadscrollviewwithpage");
// [[NSURLCache sharedURLCache] removeAllCachedResponses];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
// which a scroll event generated from the user hitting the page control triggers updates from
// the delegate method. We use a boolean to disable the delegate logic when the page control is used.
if (pageControlUsed) {
// do nothing - the scroll was initiated from the page control, not the user dragging
return;
}
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
// NSLog(#"current page %d",page);
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self unloadScrollViewWithPage:page - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self unloadScrollViewWithPage:page + 2];
count=page+1;
// [self newCountTitleSet];
// A possible optimization would be to unload the views+controllers which are no longer visible
}
// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollViewLoc
{
CGFloat pageWidth = scrollViewLoc.frame.size.width;
CGPoint translation = [scrollViewLoc.panGestureRecognizer translationInView:scrollViewLoc.superview];
int page = floor((scrollViewLoc.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
if(translation.x > 0)
{
if(_strCurrentNewsSelect!=0)
{
if(page==0)
{
NSLog(#"OK");
NSLog(#"scrollviewwillbegindragging=0");
[self DownLoadDataPrevious:[_strCurrentNewsSelect.integervalue]-1];
}
}
else{
if(page==1)
{
NSLog(#"previous button");
[self btnPreviousClick];
}
}
} else
{
// [_txtView setText:[Dic valueForKey:#"ARTICLE_BODY"]];
// [controller.view addSubview:_txtView];
// [controller.view addSubview:_txtView];
// [controller.view addSubview:_imageview];
NSLog(#"loadscrollviewwithpage else");
[self btnPreviousClick];
NSLog(#"previous news");
// if(galleryItemClick+1!=[arrGallaeryUrl count])
//
// {
//
if(page+1==[_arrUrlLinks count])
//
{
//
NSLog(#"====....>>>>>>>");
}
count=count+1;
}
}
By using this code I am able to create the view controllers according to my array count[_arrUrlLinks] but the contents are not loaded on these views. On my first view I can only see an image view in black color rest of the views are blank.
How can I get the contents loaded on these views?
I have an image slideshow with images that are being parsed with JSON and I want to run that slideshow in a background thread.
My original code:
- (void)loadVisiblePages {
// First, determine which page is currently visible
CGFloat pageWidth = self.scrollView.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
// Update the page control
self.pageControl.currentPage = page;
// Work out which pages we want to load
NSInteger firstPage = page - 1;
NSInteger lastPage = page + 1;
// Purge anything before the first page
for (NSInteger i=0; i<firstPage; i++) {
[self purgePage:i];
}
for (NSInteger i=firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
for (NSInteger i=lastPage+1; i<self.pageImages.count; i++) {
[self purgePage:i];
}
}
- (void)loadPage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Load an individual page, first seeing if we've already loaded it
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView == [NSNull null]) {
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
UIImageView *newPageView = [[UIImageView alloc] initWithImage:[self.pageImages objectAtIndex:page]];
newPageView.contentMode = UIViewContentModeScaleAspectFit;
newPageView.frame = frame;
[self.scrollView addSubview:newPageView];
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
- (void)purgePage:(NSInteger)page {
if (page < 0 || page >= self.pageImages.count) {
// If it's outside the range of what we have to display, then do nothing
return;
}
// Remove a page from the scroll view and reset the container array
UIView *pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*)pageView != [NSNull null]) {
[pageView removeFromSuperview];
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *images = _singleRelease[#"images"];
NSMutableArray *mediumImages = [NSMutableArray array];
for (NSDictionary *imageDictionary in images){
NSURL *imageURL = [NSURL URLWithString:imageDictionary[#"image_file"][#"image_file"][#"medium"][#"url"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
[mediumImages addObject:image];
}
self.pageImages = [mediumImages copy];
NSInteger pageCount = self.pageImages.count;
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 4
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
// 5
[self loadVisiblePages];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// Load the pages which are now on screen
[self loadVisiblePages];
}
I tried customizing a code sample I found online, but I cant get it to work with my code.
This is what I have so far:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *images = _singleRelease[#"images"];
NSMutableArray *mediumImages = [NSMutableArray array];
dispatch_queue_t imageQueue = dispatch_queue_create("Image Queue",NULL);
for (NSDictionary *imageDictionary in images){
dispatch_async(imageQueue, ^{
NSURL *imageURL = [NSURL URLWithString:imageDictionary[#"image_file"][#"image_file"][#"medium"][#"url"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
[mediumImages addObject:image];
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger pageCount = self.pageImages.count;
self.pageImages = [mediumImages copy];
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
});
});
}
}
This was another code sample I tried customizing but I get the same outcome.
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *images = [self.singleRelease[#"images"] copy];
__weak __typeof__(self) weakself = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableArray *mediumImages = [NSMutableArray array];
for (NSDictionary *imageDictionary in images){
NSURL *imageURL = [NSURL URLWithString:imageDictionary[#"image_file"][#"image_file"][#"medium"][#"url"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
if (image) {
[mediumImages addObject:image];
}
}
dispatch_sync(dispatch_get_main_queue(), ^{
if (weakself) {
__typeof__(self) weakself = weakself;
self.pageImages = mediumImages;
NSInteger pageCount = self.pageImages.count;
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i) {
[self.pageViews addObject:[NSNull null]];
}
};
});
});
}
Both codes load my Page Control with the correct number of slides, but the images don't appear.
Any help? Thanks.
Fixed it.
Delete viewWillAppear and then replace the current viewDidLoad with this:
/**
* Called after the controller’s view is loaded into memory.
*/
- (void)viewDidLoad
{
[super viewDidLoad];
self.release_name.text = [self.singleRelease objectForKey:#"release_name"];
if ([_singleRelease objectForKey:#"release_price"])
self.release_price.text = [NSString stringWithFormat:#"$%#",[_singleRelease objectForKey:#"release_price"]];
self.release_colorway.text = [self.singleRelease objectForKey:#"release_colorway"];
if([_singleRelease objectForKey:#"release_date"] != NULL)
{
NSString *readableDate = [_singleRelease objectForKey:#"release_date"]; // I assume that this is a string
UpcomingRelease *upcoming = [[UpcomingRelease alloc] init];
upcoming.release_date = readableDate;
self.release_date.text = [NSString stringWithFormat:#"%#", upcoming.formattedDate];
}
NSArray *images = self.singleRelease[#"images"];
// we get the image on a background queue
dispatch_queue_t imageQueue = dispatch_queue_create("Image Queue",NULL);
dispatch_async(imageQueue,
^{
NSMutableArray *mediumImages = [[NSMutableArray alloc] initWithCapacity:images.count];
// for each image url we get the image and add it to the array
for (NSDictionary *imageDictionary in images)
{
NSURL *imageURL = [[NSURL alloc] initWithString:imageDictionary[#"image_file"][#"image_file"][#"medium"][#"url"]];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
UIImage *image = [[UIImage alloc] initWithData:imageData];
[mediumImages addObject:image];
}
// once we have obtained all of the images we use them
dispatch_async(dispatch_get_main_queue(),
^{
// we get a strong pointer to the images array and set the pages count according to how many there are
self.pageImages = [mediumImages copy];
NSInteger pageCount = self.pageImages.count;
// we set the page control appropriate for the number of images that need to be presented
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
// we then make mock page views
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; ++i)
{
[self.pageViews addObject:[NSNull null]];
}
// once we have the images we load the pages with them
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
[self loadVisiblePages];
});
});
_scrollView.showsHorizontalScrollIndicator=NO;
_scrollView.showsVerticalScrollIndicator=NO;
}
The problem was you were trying to load the pages before the images had finished fetching.
I have a wallpaper app that has a paged scrollview on the main view. each page of the scrollview displays 9 images.
When the view is scrolled I'm loading the next 10 pages of images and set the previous 10 pages uiimages that I've loaded to nil to prevent memory warnings.
The problem is when the view scrolls and so the following method of scrollview gets called, there is few seconds delay before the view can scroll even though I have put the block code that loads new images in dispatch_async.
and when I comment out the whole section of the code with dispatch stuff, there is no delay.
If anyone has any idea on why this happens. please please let me know.
Thank you all so much
- (void)scrollViewDidScroll:(UIScrollView *)scrollV
{
float fractionalPage = scrollView.contentOffset.x / self.view.frame.size.width;
if (curPageNum != lround(fractionalPage)) {
curPageNum = lround(fractionalPage);
//display the page number
pageNumLabel.text = [NSString stringWithFormat:#"%d",curPageNum+1];
pageNumLabel.alpha = 1.0;
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(dismissPageNum) userInfo:nil repeats:NO];
//loading more pages with 9 image in each
lastLoadedPageNum = MIN(lastLoadedPageNum + 10, numPages - 1);
dispatch_queue_t getImages = dispatch_queue_create("Getting Images", nil);
dispatch_async(getImages, ^{
for (int i = curPageNum + 4 ; i <= lastLoadedPageNum ; i++) {
int numPicsPerPage = 9;
if (picsNames.count%9 && i == numPages-1) {
numPicsPerPage = picsNames.count%9;
}
for (int j = 0 ; j < numPicsPerPage ; j++) {
UIImage *image = [brain imageWith:[picsNames objectAtIndex:(i*9) + j]];
dispatch_async(dispatch_get_main_queue(), ^{
//loading the image to imageview
UIImageView *imageView = (UIImageView *)[scrollView viewWithTag:IMAGE_VIEWS_TAG + (i*9) + j];
imageView.image = image;
});
}
}
});
//setting old imageview images to nil to release memory
int oldFirstLoadedPageNum = firtLoadedPageNum;
firtLoadedPageNum = MAX(curPageNum - 4, 0);
for (int i = oldFirstLoadedPageNum ; i < firtLoadedPageNum ; i++) {
int numPicsPerPage = 9;
if (picsNames.count%9 && i == numPages-1) {
numPicsPerPage = picsNames.count%9;
}
for (int j = 0 ; j < numPicsPerPage ; j++) {
UIImageView *imageView = (UIImageView *)[scrollView viewWithTag:IMAGE_VIEWS_TAG + (i*9) + j];
imageView.image = nil;
[((UIActivityIndicatorView *)[imageView viewWithTag:ACTIVITY_INDICATOR_TAG]) startAnimating];
}
}
}
}
Brain method imageWith:
-(UIImage *)imageWith:(NSString *)imageName
{
NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageName];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
if (!image && [self connected]) {
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#/%#", picsURL, imageName]]]];
if (image) {
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
}
return image;
}
Clearly your code is looping which causes the delay. I think since the dispatch is inside the for loop it gets called only after a certain bit of iterations so that there is no real gain in using multi threading here.
Most likely your logic after the block with the nested for loops is causing the delay. Move that out into a separate method and run it in a separate thread.
As suggested by Mike Pollard I used
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0)
instead of
dispatch_queue_create("Getting Images", nil)
and it solved the issue.
Thanks everyone.