Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

RagingGoat

macrumors 6502
Original poster
Jun 21, 2010
307
15
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?
 

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
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?

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?
 

denzaltrueman

macrumors newbie
Sep 15, 2012
16
0
Everything performs just excellent but I can't determine how to basically run through the pictures once I've utilized on one.
 

waterskier2007

macrumors 68000
Jun 19, 2007
1,871
228
Novi, MI
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.
 

RagingGoat

macrumors 6502
Original poster
Jun 21, 2010
307
15
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
 

waterskier2007

macrumors 68000
Jun 19, 2007
1,871
228
Novi, MI
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.