Get Image from URL and display them to Image Gallery AlAsset - ios

I know this question might be asked many time but i am a beginner so kindly being gentle is a humble request.
I am trying to make an image gallery which displays all the images Of a URL.
I have used all asset framework and made a simple gallery which return the images of camera roll, I want to have the image of some URL so kindly help me to Get images from url and display them to Image Gallery
Here Is the view Controller header File
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#interface ViewController : UIViewController <UICollectionViewDelegate,UICollectionViewDataSource>
#property (retain, nonatomic) IBOutlet UICollectionView *collectionView;
#property(nonatomic, strong) NSArray *assets;
Here is the Implementation file In which I have registered An .NIB file to add Cell to my CollectionView
#import "ViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import "MyCell.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.collectionView registerNib:[UINib nibWithNibName:#"MyCell" bundle:nil] forCellWithReuseIdentifier:#"CELL"];
_assets = [#[] mutableCopy];
__block NSMutableArray *tmpAssets = [#[] mutableCopy];
// 1
here it is calliing defaultAssetsLibrary method which you can see later
ALAssetsLibrary *assetsLibrary = [ViewController defaultAssetsLibrary];
// 2
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result)
{
// 3
[tmpAssets addObject:result];
}
}];
// 4
//NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"date" ascending:NO];
//self.assets = [tmpAssets sortedArrayUsingDescriptors:#[sort]];
self.assets = tmpAssets;
// 5
[self.collectionView reloadData];
} failureBlock:^(NSError *error) {
NSLog(#"Error loading images %#", error);
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - collection view data source
- (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.assets.count;
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (MyCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CELL" forIndexPath:indexPath];
ALAsset *asset = self.assets[indexPath.row];
cell.asset = asset;
cell.backgroundColor = [UIColor redColor];
////
//=
cell.cellLabel.text = [NSString stringWithFormat:#"cell %i",indexPath.row];
return cell;
}
- (void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
ALAsset *asset = self.assets[indexPath.row];
ALAssetRepresentation *defaultRep = [asset defaultRepresentation];
UIImage *image = [UIImage imageWithCGImage:[defaultRep fullScreenImage] scale:[defaultRep scale] orientation:0];
// Do something with the image
}
And here is that method which I think returning the photo library
+ (ALAssetsLibrary *)defaultAssetsLibrary
{
static dispatch_once_t pred = 0;
static ALAssetsLibrary *library = nil;
dispatch_once(&pred, ^{
library = [[ALAssetsLibrary alloc] init];
});
return library;
}
Please Help me to get Images From URL and display them in Image Gallery.
As Far as MyCell file is concern.
Here is MYCell.m file
#interface MyCell ()
// 1
#property(nonatomic, strong) IBOutlet UIImageView *photoImageView;
#end
#implementation MyCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void) setAsset:(ALAsset *)asset
{
// 2
_asset = asset;
self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]];
}

If we are getting images from URL we don't need AlAsset for image gallery really.
I have followed this tutorial to make the image gallery Guide and Simple passed the array of url and it worked for me.

Related

UICollectionView not displaying images

I am creating an array of images selected from the phones camera roll. They are being stored but for some reason I can't get them to display in my collectionView.
in my CollectionViewController.m
- (void)viewDidLoad {
[self.photoCollectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:#"PhotoCell"];
self.assets = [[NSMutableArray alloc]init];
[super viewDidLoad];
- (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.assets.count;
}
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = (PhotoCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"PhotoCell" forIndexPath:indexPath];
ALAsset *asset = self.assets[indexPath.row];
cell.asset = asset;
cell.backgroundColor = [UIColor redColor];
return cell;
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSMutableArray *tmpAssets = [#[] mutableCopy];
[tmpAssets addObject:image];
self.assets = tmpAssets;
self.testImage.image = [self.assets objectAtIndex:0];
[picker dismissViewControllerAnimated:YES completion:Nil];
[self.photoCollectionView reloadData];
}
in my PhotoCell.h class
#interface PhotoCell : UICollectionViewCell
#property (nonatomic,strong) ALAsset *asset;
#end
in my PhotoCell.m class
#import "PhotoCell.h"
#interface PhotoCell ()
#property(nonatomic, strong) IBOutlet UIImageView *photoImageView;
#end
#implementation PhotoCell
- (void) setAsset:(ALAsset *)asset
{
_asset = asset;
self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]];
}
#end
Any help would be great thank you.

How to store PFUser objectId with RecipientId

I use Parse.com for backend, I've two views : InboxView (where I receive images from friends), and ChatView.
When I send images, I send images with recipientIds of user (that can be multiple users) in "Messages" class (parse).
I receive images in my InboxView, I can see in cell for row the name of the friend that send images.
I would like that when I select a row (username who sends me image) that stores the PFUser objectId of the user who sends me the image, and not all of the recipientIds.
How can I make that ?
Here is my code :
Inbox.h :
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <MediaPlayer/MediaPlayer.h>
#interface InboxViewController : UITableViewController
#property (nonatomic, strong) NSArray *messages;
#property (nonatomic, strong) PFObject *selectedMessage;
#property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
#property (nonatomic, strong) UIImage *MindleNav;
- (UIImage *)resizeImage:(UIImage *)image toWidth:(float)width andHeight:(float)height;
#end
and inbox.m :
#import "InboxViewController.h"
#import "ImageViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "LoginViewController.h"
#import "FriendsViewController.h"
#interface InboxViewController ()
#end
#implementation InboxViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.MindleNav = [UIImage imageNamed:#"MindleNavItem.png"];
UIImage *newImage = [self resizeImage:self.MindleNav toWidth:150.0f andHeight:48.0f];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:newImage];
self.MindleNav = newImage;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Messages"];
[query whereKey:#"recipientIds" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
// We found messages!
self.messages = objects;
[self.tableView reloadData];
}
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFObject *message = [self.messages objectAtIndex:indexPath.row];
cell.textLabel.text = [message objectForKey:#"senderName"];
NSString *fileType = [message objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
cell.imageView.image = [UIImage imageNamed:#"icon_image"];
}
else {
// cell.imageView.image = [UIImage imageNamed:#"icon_video"];
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedMessage = [self.messages objectAtIndex:indexPath.row];
NSString *fileType = [self.selectedMessage objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
[self performSegueWithIdentifier:#"showImage" sender:self];
}
else {
// File type is text
// // File type is video
// PFFile *videoFile = [self.selectedMessage objectForKey:#"file"];
// NSURL *fileUrl = [NSURL URLWithString:videoFile.url];
// self.moviePlayer.contentURL = fileUrl;
// [self.moviePlayer prepareToPlay];
// UIImage *thumbnail = [self thumbnailFromVideoAtURL:self.moviePlayer.contentURL];
//
//// [self.moviePlayer thumbnailImageAtTime:0 timeOption:MPMovieTimeOptionNearestKeyFrame];
//
// // Add it to the view controller so we can see it
// UIImageView *imageView = [[UIImageView alloc] initWithImage:thumbnail];
// [self.moviePlayer.backgroundView addSubview:imageView];
// [self.moviePlayer setFullscreen:YES animated:YES];
}
// Delete it!
NSMutableArray *recipientIds = [NSMutableArray arrayWithArray:[self.selectedMessage objectForKey:#"recipientIds"]];
NSLog(#"Recipients: %#", recipientIds);
if ([recipientIds count] == 1) {
// Last recipient - delete!
// [self.selectedMessage deleteInBackground];
}
else {
// Remove the recipient and save
// [recipientIds removeObject:[[PFUser currentUser] objectId]];
// [self.selectedMessage setObject:recipientIds forKey:#"recipientIds"];
// [self.selectedMessage saveInBackground];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showImage"]) {
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
ImageViewController *imageViewController =
(ImageViewController *)segue.destinationViewController;
imageViewController.message = self.selectedMessage;
}
}
- (UIImage *)thumbnailFromVideoAtURL:(NSURL *)url
{
AVAsset *asset = [AVAsset assetWithURL:url];
// Get thumbnail at the very start of the video
CMTime thumbnailTime = [asset duration];
thumbnailTime.value = 0;
// Get image from the video at the given time
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:thumbnailTime actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return thumbnail;
}
- (UIImage *)resizeImage:(UIImage *)truckImage toWidth:(float)width andHeight:(float)height {
CGSize newSize = CGSizeMake(width, height);
CGRect newRectangle = CGRectMake(0, 0, width, height);
UIGraphicsBeginImageContext(newSize);
[self.MindleNav drawInRect:newRectangle];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
#end

Fetching Image from Parse class

Beginner here guys. I already managed to get the text from Parse class to table view. In the same class i have another column where I put the associated image file and somehow i could not get the image file. I will be glad if you can help me with this issue. Parse class name is News and the column i would like to get is imageFile. Here is my code.
.h file
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "TableCell.h"
#interface ViewController : UIViewController <UITableViewDelegate> {
NSArray *events;
}
#property (weak, nonatomic) IBOutlet UITableView *newsTable;
#end
.m file
#import "ViewController.h"
#import "TableCell.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize newsTable;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self performSelector: #selector(retreiveFromParse)];
}
- (void) retreiveFromParse {
PFQuery *retrieveEvents = [PFQuery queryWithClassName:#"News"];
[retrieveEvents findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
events = [[NSArray alloc] initWithArray:objects];
}
[newsTable reloadData];
}];
}
//*********************Setup table of folder names ************************
//get number of sections in tableview
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
//get number of rows by counting number of folders
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return events.count;
}
//setup cells in tableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//setup cell
static NSString *CellIdentifier = #"EventCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
PFObject *tempObject = [events objectAtIndex:indexPath.row];
cell.TitleLabel.text = [tempObject objectForKey:#"Event"];
return cell;
}
//user selects folder to add tag to
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cell tapped");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
My Cell.h
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface TableCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#end
My cell.m
#import "TableCell.h"
#implementation TableCell
#synthesize TitleLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
Just after
PFObject *tempObject = [events objectAtIndex:indexPath.row];
cell.TitleLabel.text = [tempObject objectForKey:#"Event"];
Write below lines..
PFFile *imageFile = [tempObject objectForKey:#"image"];
PFImageView *imageView = [[PFImageView alloc] init];
imageView.file = imageFile;
[imageView loadInBackground:^(UIImage *img,NSError *error){
if(!error)
{
UIImageView *yourImageView = [[UIImageView alloc] init];
yourImageView.image = imageView.image;
/*OR*/
cell.imageView.image = imageView.image;
}
}];
This might get you going.
This will fetch the associated file and put it in cell.imageView, which is a PFImageView (the Parse edition of UIImageView):
PFObject *tempObject = [events objectAtIndex:indexPath.row];
cell.TitleLabel.text = [tempObject objectForKey:#"Event"];
PFFile *imageFile = [tempObject objectForKey:#"imageFile"];
if (imageFile) {
cell.imageView.file = imageFile;
[cell.imageView loadInBackground];
} else {
cell.imageView.image = [UIImage imageNamed:#"AvatarPlaceholder.png"];
}

MWPhotoBrowser not showing the correct image when selected from a collection view

In my app, there's only 2 views. First view is a collection view and when you tap on an image, it goes to the MWPhotoBrowser to view the image in it's full size.
I'm retrieving ~100 images over the internet and adding them to a NSMutableArray.
There's a problem with this. When I run the app for the first time and select a thumbnail image from the grid it shows the last image. Not the one I selected. Note that I emphasized on the first time because it only happens in the first time. If I go back and tap on another image, it correctly shows the selected one. Below is a screenshot of how its supposed to work.
Here is the code
#import "UIImageView+WebCache.h"
#import "ViewController.h"
#import "MWPhotoBrowser.h"
#import "Image.h"
#import "ImageCell.h"
#interface ViewController () <UICollectionViewDelegate, UICollectionViewDataSource, MWPhotoBrowserDelegate>
#property (strong, nonatomic) NSMutableArray *images;
#property (strong, nonatomic) NSMutableArray *browserImages;
#property (strong, nonatomic) MWPhotoBrowser *browser;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
self.browser.displayActionButton = YES;
self.browser.displayNavArrows = YES;
self.browser.displaySelectionButtons = NO;
self.browser.zoomPhotosToFill = YES;
self.browser.alwaysShowControls = YES;
self.browser.enableGrid = NO;
self.browser.startOnGrid = NO;
self.browser.wantsFullScreenLayout = NO;
[self.browser showNextPhotoAnimated:YES];
[self.browser showPreviousPhotoAnimated:YES];
[self loadImages];
}
- (void)loadImages
{
self.images = [[NSMutableArray alloc] init];
self.browserImages = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", HOST_URL, #"All_Images.php"]];
NSData *jsonResults = [NSData dataWithContentsOfURL:url];
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:jsonResults options:0 error:NULL];
NSDictionary *images = results[#"Images"];
for (NSDictionary *img in images) {
Image *imageObj = [[Image alloc] init];
imageObj.imageId = [img objectForKey:#"id"];
imageObj.imageName = [img objectForKey:#"name"];
// Get the full image path
NSString *fullImagePath = [NSString stringWithFormat:#"%#%#", HOST_URL, [img objectForKey:#"full_image"]];
imageObj.imagePath = fullImagePath;
// Get the thumbnail image path depending on the device
NSString *thumbnailPath;
if (DEVICE_IS_PAD) {
thumbnailPath = [NSString stringWithFormat:#"%#%#", HOST_URL, [img objectForKey:#"thumbnail_ipad"]];
} else {
thumbnailPath = [NSString stringWithFormat:#"%#%#", HOST_URL, [img objectForKey:#"thumbnail_iphone"]];
}
imageObj.imageThumbnail = thumbnailPath;
// Creates an object for each image and fill it with the retrieved info
[self.images addObject:imageObj];
// This array stores the image paths for later use (displaying them in a photo browser)
MWPhoto *browserImage = [MWPhoto photoWithURL:[NSURL URLWithString:imageObj.imagePath]];
browserImage.caption = imageObj.imageName;
[self.browserImages addObject:browserImage];
}
[self.collectionView reloadData];
}
#pragma mark - MWPhotoBrowserDelegate
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser
{
return self.browserImages.count;
}
- (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index
{
if (index < self.browserImages.count) {
return self.browserImages[index];
}
return nil;
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.images.count;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ImageCell";
ImageCell *cell = (ImageCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
Image *image = self.images[indexPath.row];
[cell.imageView setImageWithURL:[NSURL URLWithString:image.imageThumbnail] placeholderImage:[UIImage imageNamed:#"placeholder"]];
return cell;
}
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// Opens the image browser
[self.browser setCurrentPhotoIndex:indexPath.row];
[self.navigationController pushViewController:self.browser animated:YES];
}
#end
I cannot find out why it shows the last image of the grid the first time I select an image. I have uploaded a demo project with the issue so it'll be easier for you to take a quick look at it.
https://www.dropbox.com/s/tp6a67f83l0rzin/PhotoBrowserTest.zip
I'd really appreciate anyone's help to correct this problem.
Thank you.
Change in your project these methods
- (NSUInteger)numberOfPhotos {
if (_photoCount == NSNotFound || _photoCount == 0) {
if ([_delegate respondsToSelector:#selector(numberOfPhotosInPhotoBrowser:)]) {
_photoCount = [_delegate numberOfPhotosInPhotoBrowser:self];
} else if (_depreciatedPhotoData) {
_photoCount = _depreciatedPhotoData.count;
}
}
if (_photoCount == NSNotFound) _photoCount = 0;
return _photoCount;
}
AND
- (id)initWithDelegate:(id <MWPhotoBrowserDelegate>)delegate {
if ((self = [self init])) {
_delegate = delegate;
[self setCurrentPhotoIndex:0];
}
return self;
}
You need to check if your _photoCount == 0, because the first time you donĀ“t have this info and _photoCount will be 0, but the second time your numberOfPhotosInPhotoBrowser will be the right

Clear Collection View Cells when new ones are generated (iOS7 - AFNetworking)

I have a Collection View Controller with Cells that get their content from a JSON call. Each Cell has a Scroll View (an image slideshow). I noticed that the slideshows are being loaded on top of the old ones (I could see the slideshow from the old cells appear right before the new slideshow is loaded). Or if I swipe to let's say the third image of my first cell and then scroll the fourth cell, it shows my the third image (instead of the first), but the Page Control will show that that's the first slide.
How can I "clear" the old cells (or at least clear the Scroll View, or stop it from being reused) while the new ones are being generated?
Article.h (NSObject)
#interface Article : NSObject
#property (readonly) NSURL *imageURL;
#property (nonatomic, strong) NSArray *images;
- (instancetype)initWithAttributes:(NSDictionary *)attributes;
+ (void)latestNewsWithBlock:(void (^)(NSArray *news, NSError *error))block;
#end
#pragma mark -
#interface ArticleImage : NSObject
#property (readonly, nonatomic, strong) NSURL *URL;
- (instancetype)initWithAttributes:(NSDictionary *)attributes;
#end
Article.m (NSObject)
#interface Article ()
#property (readwrite, nonatomic, strong) NSURL *URL;
#end
#implementation Article
- (instancetype)initWithAttributes:(NSDictionary *)attributes {
self = [super init];
if (!self) {
return nil;
}
self.URL = [NSURL URLWithString:attributes[#"url"]];
NSMutableArray *mutableImages = [NSMutableArray array];
for (NSDictionary *imageAttributes in attributes[#"photos"]) {
NSDictionary *imageFileAttributes = [imageAttributes valueForKeyPath:#"photo_file.photo_file"];
ArticleImage *image = [[ArticleImage alloc] initWithAttributes:imageFileAttributes];
[mutableImages addObject:image];
}
self.images = mutableImages;
return self;
}
- (NSURL *)imageURL {
return [[self.images firstObject] URL];
}
+ (void)latestNewsWithBlock:(void (^)(NSArray *news, NSError *error))block {
[[DeadstockAPIManager sharedManager] GET:#"articles" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
NSMutableArray *mutableNews = [NSMutableArray array];
for (NSDictionary *attributes in JSON[#"articles"]) {
Article *news = [[Article alloc] initWithAttributes:attributes];
[mutableNews addObject:news];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if (block) {
block([NSArray arrayWithArray:mutableNews], nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (block) {
block(nil, error);
}
}];
}
#end
#pragma mark -
#interface ArticleImage ()
#property (readwrite, nonatomic, strong) NSURL *URL;
#property (readwrite, nonatomic, strong) NSURL *thumbnailURL;
#end
#implementation ArticleImage
- (instancetype)initWithAttributes:(NSDictionary *)attributes {
self = [super init];
if (!self) {
return nil;
}
self.URL = [NSURL URLWithString:[attributes valueForKeyPath:#"thumb.url"]];
return self;
}
Collection View Controller
- (void)setLatestNews:(NSArray *)latestNews {
_latestNews = latestNews;
[self.collectionView reloadData];
}
- (void)loadData:(id)sender {
[Article latestNewsWithBlock:^(NSArray *news, NSError *error) {
self.latestNews = news;
}];
}
#pragma mark - UIViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[ArticleCell class] forCellWithReuseIdentifier:#"ArticleCell"];
[self loadData:nil];
}
#pragma mark - UICollectionViewDataSource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"articleCell";
ArticleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
cell.article = [self.latestNews objectAtIndex:indexPath.row];
return cell;
}
Collection View Cell
#interface ArticleCell ()
#property (readwrite, nonatomic, strong) NSArray *pageImages;
#end
#implementation ArticleCell
- (void)setArticle:(Article *)article {
_article = article;
self.pageImages = [self.article.images valueForKeyPath:#"URL"];
NSUInteger pageCount = [self.pageImages count];
self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = pageCount;
self.pageControl.hidden = (pageCount == 1);
for (NSInteger page = 0; page < pageCount; page++) {
CGRect frame = self.scrollView.bounds;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0.0f;
UIImageView *imageView = [[UIImageView alloc] init];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.frame = frame;
[imageView setImageWithURL:self.pageImages[page]];
[self.scrollView addSubview:imageView];
}
CGSize pagesScrollViewSize = self.scrollView.frame.size;
self.scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * self.pageImages.count, pagesScrollViewSize.height);
}
Thanks.
Example project can be found here: http://www.filedropper.com/collectionviewtest
Implement this as a public method in your ArticleCell:
- (void)cleanForReuse
{
[[self.scrollView subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
self.scrollView.contentSize = CGSizeZero;
}
- (void)prepareForReuse
{
[super prepareForReuse];
self.pageImages = nil;
}
Then update your code to call cleanForReuse before reusing the cell:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"articleCell";
ArticleCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:identifier
forIndexPath:indexPath];
[cell cleanForReuse];
cell.article = [self.latestNews objectAtIndex:indexPath.row];
return cell;
}
You're seeing this because the cells are being reused (which is a good thing for performance reasons).
When you have old content that will need to be removed from a cell when it gets reused, you will need to remove it in collectionView:cellForItemAtIndexPath:.
In your case, you will want to call removeFromSuperview on all of the imageViews that you added to the scrollView before adding the new imageViews.
You can also do some reuse preparation in the UICollectionViewCell method prepareForReuse. However, for performance reasons in UITableViewCells Apple recommends that "you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state.". Presumably, this same recommendation applies to UICollectionViewCells.

Resources