Swipe Through Images

Discussion in 'iOS Programming' started by RagingGoat, Dec 31, 2012.

  1. RagingGoat macrumors 6502

    Joined:
    Jun 21, 2010
    #1
    I have a uicollectionview that shows the newest 50 images from a Flickr page. I can tap a thumbnail cell and show a larger image. Everything works just fine but I can't figure out how to simply swipe through the images once I've tapped on one. I've searched for any info on how to do this but haven't been able to find anything. Can anyone on here help me out with any insights or links to useful info?
     
  2. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #2
    You're going to have to provide more information. When the user taps on an item, do you push another view controller that is a detail view? If not, how do you present the larger item?
     
  3. denzaltrueman macrumors newbie

    Joined:
    Sep 15, 2012
    #3
    Everything performs just excellent but I can't determine how to basically run through the pictures once I've utilized on one.
     
  4. RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #4

    Yes.
     
  5. waterskier2007 macrumors 68000

    waterskier2007

    Joined:
    Jun 19, 2007
    Location:
    White Lake, MI
    #5
    Would it be possible to add gesture recognizers to your detail view, detect when a swipe happens, and then update the image being displayed? I would guess that you have the images stored in some kind of array for the UICollectionView (Not certain because I have never used UICollectionView), so you could just pick the next (or previous) object from that array when the user swipes and refresh the detail view with the new image.
     
  6. RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #6
    Here is my code.

    Code:
    //
    //  KFBFlickrViewController.h
    //  KFBNewsroom
    
    #import <UIKit/UIKit.h>
    #import <dispatch/dispatch.h>
    #import "KFBFlickrPhotoManager.h"
    #import "KFBImageDetailViewController.h"
    
    @interface KFBFlickrViewController : UIViewController <NSURLConnectionDelegate,NSURLConnectionDataDelegate, UICollectionViewDataSource,UICollectionViewDelegate,FlickrPhotoDelegate>
    {
    
        NSMutableArray *imageInfo;
    }
    
    @property (retain) NSMutableArray * imageInfo;
    @property (retain) KFBFlickrPhotoManager * imageManager;
    @property (retain) NSString * html;
    
    @property (nonatomic, retain) NSString *apiKey;
    @property (retain, nonatomic) IBOutlet UICollectionView *photoCollectionView;
    @property (retain) KFBImageDetailViewController *imageDetailViewController;
    @end
    
    Code:
    //
    //  KFBFlickrViewController.m
    //  KFBNewsroom
    
    #import "KFBFlickrViewController.h"
    #import "KFBFlickrPhoto.h"
    
    @interface KFBFlickrViewController ()
    
    @end
    
    @implementation KFBFlickrViewController
    
    @synthesize apiKey=apiKey;
    @synthesize photoCollectionView, imageManager, imageInfo,imageDetailViewController;
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            apiKey = @"a70fe2e828e66660c74ce0a7c34a55aa";
            NSString *urlString = [NSString stringWithFormat:@"http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=%@&per_page=50&user_id=52540720@N02&format=json&nojsoncallback=1", apiKey];
            
            NSURL *url = [NSURL URLWithString:urlString];
            
            imageInfo = [NSMutableArray array];
            
            self.imageInfo = [[NSMutableArray alloc] init];
            self.imageManager = [[KFBFlickrPhotoManager alloc] initWithURL:url delegate:self];
            [imageManager process];
            
    
            imageInfo = [NSMutableArray array];
             [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(imageUpdated:) name:@"com.KFB.imageupdated" object:nil];
            // Custom initialization
            
            
        }
        return self;
    }
    
    -(void)viewDidAppear:(BOOL)animated
    {
        //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(imageUpdated:) name:@"com.KFB.imageupdated" object:nil];
    }
    
    -(void)viewDidDisappear:(BOOL)animated
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"com.razeware.imagegrabber.imageupdated" object:nil];
    }
    
    -(void)showFlickr
    {
        NSURL *url = [NSURL URLWithString:@"http://www.kyfb.com/photos"];
        [[UIApplication sharedApplication] openURL:url];
    }
    
    -(void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.navigationItem.title = @"KFB On Flickr!";
        UINib *cellNib = [UINib nibWithNibName:@"CVCell" bundle:nil];
        [self.photoCollectionView registerNib:cellNib forCellWithReuseIdentifier:@"photoCell"];
        
        UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
        [flowLayout setItemSize:CGSizeMake(75, 75)];
        [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
        [flowLayout setSectionInset:UIEdgeInsetsMake(10, 10, 10, 10)];
        [self.photoCollectionView setCollectionViewLayout:flowLayout];
        
        UIBarButtonItem *openFlickr = [[UIBarButtonItem alloc] initWithTitle:@"More Photos" style:UIBarButtonItemStyleBordered target:self action:@selector(showFlickr)];
        self.navigationItem.rightBarButtonItem = openFlickr;
    }
    
    -(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        
        static NSString *cellIdentifier = @"photoCell";
        
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
        
        KFBFlickrPhoto * info = [imageInfo objectAtIndex:indexPath.row];
        UIImageView *imageView = (UIImageView*)[cell viewWithTag:2020];
        imageView.image = info.image;
    
        return cell;
    }
    -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
    {
        KFBFlickrPhoto *photo = [imageInfo objectAtIndex:indexPath.row];
            self.imageDetailViewController = [[KFBImageDetailViewController alloc] initWithNibName:@"KFBImageDetailViewController" bundle:[NSBundle mainBundle]];
        imageDetailViewController.photo = photo;
        [self.navigationController pushViewController:imageDetailViewController animated:YES];
    }
    
    
    -(void)imagesAvailable:(NSArray *)images done:(BOOL)done {
        
        NSLog(@"Image infos available: %d!", images.count);
        
        NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:images.count];
        for(int i = imageInfo.count; i < imageInfo.count + images.count; ++i) {
            NSIndexPath * indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            [indexPaths addObject:indexPath];
        }
        [imageInfo addObjectsFromArray:images];
        [photoCollectionView insertItemsAtIndexPaths:indexPaths];
        //[photoCollectionView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
        
    }
    
    
    - (void)imageUpdated:(NSNotification *)notif {
        
        UIImage *info = [notif object];
        int row = [imageInfo indexOfObject:info];
        NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:0];
        
        NSLog(@"Image for row %d updated!", row);
        [photoCollectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
        //[photoCollectionView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    
    }
    -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
    {
        return 1;
    }
    
    -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return [imageInfo count];
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    
    Code:
    //
    //  KFBImageDetailViewController.h
    //  KFBNewsroom
    
    #import <UIKit/UIKit.h>
    #import "KFBFlickrPhoto.h"
    
    @interface KFBImageDetailViewController : UIViewController <NSURLConnectionDataDelegate,NSURLConnectionDelegate, UIActionSheetDelegate>
    
    
    @property (retain) KFBFlickrPhoto *photo;
    @property (nonatomic, retain) IBOutlet UIImageView *imageView;
    @property (nonatomic, retain) IBOutlet UILabel *nameLabel;
    @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingIndicator;
    - (IBAction)tappedImage:(id)sender;
    
    @end
    
    Code:
    //
    //  KFBImageDetailViewController.m
    //  KFBNewsroom
    
    #import "KFBImageDetailViewController.h"
    
    @interface KFBImageDetailViewController ()
    {
        NSMutableData *responseData;
    }
    
    @end
    
    @implementation KFBImageDetailViewController
    
    @synthesize imageView,photo, nameLabel,loadingIndicator;
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    -(void)viewWillAppear:(BOOL)animated
    {
        nameLabel.text = photo.name;
        
        NSURLRequest *request = [NSURLRequest requestWithURL:photo.bigImageName];
        (void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
    }
    
    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [responseData appendData:data];
    }
    
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        [loadingIndicator removeFromSuperview];
        UIImage *image = [UIImage imageWithData:responseData];
        
        imageView.image = image;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        responseData = [NSMutableData data];
        // Do any additional setup after loading the view from its nib.
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (IBAction)tappedImage:(id)sender {
        UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"" delegate:self cancelButtonTitle:@"Cancel"
                                                   destructiveButtonTitle:nil otherButtonTitles: @"Save To Camera Roll", nil, nil];
    	
        sheet.actionSheetStyle = self.navigationController.navigationBar.barStyle;
        [sheet showInView:self.parentViewController.tabBarController.view];
    }
    
    - (void)actionSheet:(UIActionSheet *)modalView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        
        switch (buttonIndex)
        {
            case 0:
    			[self saveToCameraRoll];
    			break;
            default:
                break;
        }
        
    }
    
    -(void)saveToCameraRoll
    {
        UIImageWriteToSavedPhotosAlbum(imageView.image, self,
                                       @selector(image:didFinishSavingWithError:contextInfo:), nil);
    }
    
    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
      contextInfo:(void *)contextInfo
    {
    
        if (error != NULL)
        {
            NSLog(@"error: %@", error);
            
        }
        else  // No errors
        {
            
        }
    }
    @end
    
    Code:
    //
    //  KFBFlickrPhotoManager.h
    //  KFBNewsroom
    
    #import <Foundation/Foundation.h>
    #import <dispatch/dispatch.h>
    
    @protocol FlickrPhotoDelegate
    - (void)imagesAvailable:(NSArray *)images done:(BOOL)done;
    @end
    
    @interface KFBFlickrPhotoManager : NSObject <NSURLConnectionDataDelegate,NSURLConnectionDelegate> {
        dispatch_queue_t backgroundQueue;
        NSMutableData *responseData;
        
        // Titles of images
        NSMutableArray  *photoTitles;
        // Image data (thumbnail)
        NSMutableArray  *photoSmallImageData;
        NSMutableArray  *photoURLsLargeImage;
    }
    
    @property (retain) NSURL *theURL;
    @property (assign) id<FlickrPhotoDelegate> delegate;
    
    - (id)initWithURL:(NSURL*)url delegate:(id<FlickrPhotoDelegate>) theDelegate;
    - (void)process;
    
    @end
    
    Code:
    //
    //  KFBFlickrPhotoManager.m
    //  KFBNewsroom
    
    #import "KFBFlickrPhotoManager.h"
    #import "KFBFlickrPhoto.h"
    @implementation KFBFlickrPhotoManager
    
    @synthesize theURL,delegate;
    
    - (void)process {
        dispatch_async(backgroundQueue, ^(void) {
            [self requestFlickr];
        });
    }
    
    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [responseData appendData:data];
    }
    
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        [self processResults];
    }
    
    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        NSLog(@"error: %@",error);
    }
    
    -(void)requestFlickr
    {
        //NSURLConnection must be called on main thread
        NSURLRequest *request = [NSURLRequest requestWithURL:theURL];
        dispatch_async(dispatch_get_main_queue(), ^(void) {
        (void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
        });
    }
    -(void)processResults
    {
        NSError *error;
        NSDictionary *results = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONWritingPrettyPrinted error:&error];
        
        if (error) {
            NSLog(@"error: %@",error);
        }
        
        NSArray *photos = [[results objectForKey:@"photos"] objectForKey:@"photo"];
        
         NSMutableArray * images = [NSMutableArray array];
        
        for (NSDictionary *photo in photos)
        {
            // image title
            NSString *title = [photo objectForKey:@"title"];
            
            
            [photoTitles addObject:(title.length > 0 ? title : @"Untitled")];
            
            // builds URL for image, adds _s for small image (75x75)
            
            NSString *photoURLString =
            [NSString stringWithFormat:@"http://farm%@.static.flickr.com/%@/%@_%@_s.jpg",
             [photo objectForKey:@"farm"], [photo objectForKey:@"server"],
             [photo objectForKey:@"id"], [photo objectForKey:@"secret"]];
            
            NSLog(@"photoURLString: %@", photoURLString);
            
            KFBFlickrPhoto *flickrPhoto = [[KFBFlickrPhoto alloc] initWithSourceURL:[NSURL URLWithString:photoURLString]];
            flickrPhoto.name = title;
            // build an array of the image data
            [images addObject:flickrPhoto];
            
            
            
            // Build the URL to the large image
            photoURLString =
            [NSString stringWithFormat:@"http://farm%@.static.flickr.com/%@/%@_%@_b.jpg",
             [photo objectForKey:@"farm"], [photo objectForKey:@"server"],
             [photo objectForKey:@"id"], [photo objectForKey:@"secret"]];
            [photoURLsLargeImage addObject:[NSURL URLWithString:photoURLString]];
            flickrPhoto.bigImageName = [NSURL URLWithString:photoURLString];
            NSLog(@"photoURLsLargeImage: %@\n\n", photoURLString);
        }
    
        // Notify delegate in main thread
        dispatch_async(dispatch_get_main_queue(), ^(void) {
            [delegate imagesAvailable:images done:YES];
        });
        
    }
    
    - (id)initWithURL:(NSURL*)url delegate:(id<FlickrPhotoDelegate>) theDelegate {
        
        if ((self = [super init])) {
            theURL = url;
            delegate = theDelegate;
            backgroundQueue = dispatch_queue_create("com.KFB.bgqueue", NULL);
            photoTitles = [NSMutableArray array];
            // Image data (thumbnail)
            responseData = [NSMutableData data];
            photoSmallImageData = [NSMutableArray array];
            photoURLsLargeImage = [NSMutableArray array];
        }
        return self;
    }
    @end
    
    Code:
    //
    //  KFBFlickrPhoto.h
    //  KFBNewsroom
    
    #import <Foundation/Foundation.h>
    
    @interface KFBFlickrPhoto : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
    
    
    - (id)initWithSourceURL:(NSURL *)URL;
    
    @property (retain) NSURL * sourceURL;
    @property (retain) NSURL * bigImageName;
    @property (nonatomic, retain) UIImage * image;
    @property (nonatomic, retain) NSString *name;
    
    @end
    
    Code:
    //
    //  KFBFlickrPhoto.m
    //  KFBNewsroom
    
    #import "KFBFlickrPhoto.h"
    
    
    @implementation KFBFlickrPhoto
    {
        NSMutableData *responseData;
    }
    @synthesize sourceURL;
    @synthesize bigImageName;
    @synthesize image;
    @synthesize name;
    - (void)getImage {
        
        NSLog(@"Getting %@...", sourceURL);
        dispatch_async(dispatch_get_main_queue(), ^(void) {
        NSURLRequest *request = [NSURLRequest requestWithURL:sourceURL];
        (void)[[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
            });
    }
    
    - (id)initWithSourceURL:(NSURL *)url {
        if ((self = [super init])) {
            sourceURL = url;
            responseData = [NSMutableData data];
            [self getImage];
        }
        return self;
    }
    
    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [responseData appendData:data];
    }
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        image = [UIImage imageWithData:responseData];
        NSLog(@"Test");
        dispatch_async(dispatch_get_main_queue(), ^(void) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"com.KFB.imageupdated" object:self];
        });
    }
    @end
    
     
  7. waterskier2007 macrumors 68000

    waterskier2007

    Joined:
    Jun 19, 2007
    Location:
    White Lake, MI
    #7
    So from your code it seems like it would be easy enough. Just implement swipe gestures on the detail controller and then when they swipe left or right, grab the next or previous photo from back on the UICollectionView, and refresh the detail controller. Since the photo information seems to just be a URL, you could pass the array of FlickrPhotos to the detail controller.
     

Share This Page