ios 如何创建自定义 UICollectionViewCell 并将图像从 URL 添加到它?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20451578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a custom UICollectionViewCell and add image from URL to it?
提问by KennyVB
i want to load my images i've got from flickr into uicollectionsview i followed allot of guides but they all fall apart when i have to do this
我想将我从 flickr 获得的图像加载到 uicollectionsview 我遵循了很多指南但是当我必须这样做时它们都崩溃了
cell.imageView.image
it basically says it can't find imageView in object of uicollectionsviewcell
它基本上说它在 uicollectionsviewcell 的对象中找不到 imageView
i also tried a method like this, but it didn't work
我也试过这样的方法,但是没有用
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"flickerCell";
UICollectionViewCell *flickerCell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
UIImageView *recipeImageView = (UIImageView *)[flickerCell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
[flickerCell addSubview:recipeImageView];
return flickerCell;
}
recipieImageView is something i got some a tutorial. my cell is named flickerCell in the storyboard and photoURLs has 33 objects i can view in code . so it's all there. also photoURLs is a NSMutablearray how ever. in this method my recipeImageView returns nill ??? i have a cell.h which has the imageView
recipieImageView 是我得到了一些教程的东西。我的单元格在情节提要中被命名为 flickerCell,而 photoURLs 有 33 个我可以在代码中查看的对象。所以一切都在那里。photoURLs 还是一个 NSMutablearray。在这种方法中,我的 recipeImageView 返回 nill ??? 我有一个带有 imageView 的 cell.h
#import <UIKit/UIKit.h>
@interface Cell : UICollectionViewCell
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@end
so if anyone know a way i can display all the images that photoURLs has in a uicollectionview it would be very helpful
因此,如果有人知道我可以在 uicollectionview 中显示 photoURLs 的所有图像的方法,那将非常有帮助
UPDATEi now tried a new way but still not working. imageView returns nil
更新我现在尝试了一种新方法,但仍然无法正常工作。imageView 返回 nil
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"flickerCell";
Cell *flickerCell = (Cell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
return flickerCell;
}
UPDATE AGAIN
再次更新
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"flickerCell";
Cell *flickerCell = (Cell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSLog(@"flickercell = %@", flickerCell);
flickerCell.backgroundColor = [UIColor whiteColor];
flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
return flickerCell;
} with this in viewdidload
在 viewdidload 中使用这个
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:@"flickerCell"];
NSLOG of flickerCell returns this :
flickerCell 的 NSLOG 返回这个:
flickercell = <Cell: 0x9dec2f0; baseClass = UICollectionViewCell; frame = (0 0; 120 115); layer = <CALayer: 0x9dec430>>
回答by AXE
As I get it you are using a custom UICollectionViewCell. However in the method you pasted you create a pointer to UICollectionViewCell which has no built-in UIImageView. So that's why you get the error in the first try. About the second - did you register your custom UICollectionViewCell class with the CollectionView?
据我所知,您正在使用自定义 UICollectionViewCell。但是,在您粘贴的方法中,您创建了一个指向 UICollectionViewCell 的指针,该指针没有内置的 UIImageView。所以这就是为什么你在第一次尝试时就会出错。关于第二个 - 您是否使用 CollectionView 注册了您的自定义 UICollectionViewCell 类?
======
======
Edit: after a long chat with the poster we solved all the problems.
编辑:与海报长时间聊天后,我们解决了所有问题。
- The first one was that the registered class was UICollectionViewCell, not the inherited custom one.
- The second problem was that the view was actually in a xib file, so
registerNib:forCellWithReuseIdentifier:
should be used instead ofregisterClass:forCellWithReuseIdentifier:
- The third one was that the custom cell was configured in a storyboard xib instead of its own xib file that is wired with the custom class ("Cell" in our case)
- And fourth main problem was that UIImage was incorrectly created with
imageNamed:
which should be used only for images that are embedded in the project. The correct way to create the UIImage in our case is:flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
- 第一个是注册的类是 UICollectionViewCell,而不是继承的自定义类。
- 第二个问题是视图实际上是在一个 xib 文件中,所以
registerNib:forCellWithReuseIdentifier:
应该使用而不是registerClass:forCellWithReuseIdentifier:
- 第三个是自定义单元格是在故事板 xib 中配置的,而不是它自己的与自定义类连接的 xib 文件(在我们的例子中是“单元格”)
- 第四个主要问题是 UIImage 被错误地创建,
imageNamed:
它应该只用于嵌入到项目中的图像。在我们的例子中创建 UIImage 的正确方法是:flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
回答by Bhumeshwer katre
It may help you.
它可能会帮助你。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"flickerCell";
Cell *flickerCell = (Cell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
flickerCell.imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
return flickerCell;
}
回答by Vignesh Kumar
You can easily create a custom UICollectionViewCell class with custom the animation while tap the UICollectionViewCell. So, You don't need to add any specific method/action for the animation.
您可以在点击 UICollectionViewCell 时轻松创建自定义动画的自定义 UICollectionViewCell 类。因此,您不需要为动画添加任何特定的方法/动作。
- In storyboard - Add a UICollectionViewCell with cell identifier, UIImageView and UILabel.
- Assign both UIImageView and UILabel property to Storyboard cell.
Import the 'UviCollectionCell.h' in your view controller.
In YourViewController.h
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath { UviCollectionCell *cell = (UviCollectionCell *) [cv dequeueReusableCellWithReuseIdentifier:@"collection_cell" forIndexPath:indexPath]; [cell.cellImageView setBackgroundColor: [UIColor randomColor]]; // You can add your image here. cell.cellImageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]]; [cell.cellTitle setText:[NSString stringWithFormat:@"S %ld - R %ld",(long)indexPath.section,(long)indexPath.row]]; //cell.backgroundColor = [UIColor randomColor]; return cell; }
UviCollectionCell.h
#import <UIKit/UIKit.h> @interface UviCollectionCell : UICollectionViewCell<UIGestureRecognizerDelegate> @property (strong, nonatomic) IBOutlet UIImageView *cellImageView; @property (strong, nonatomic) IBOutlet UILabel *cellTitle; @end
UviCollectionCell.m
#import "UviCollectionCell.h" @implementation UviCollectionCell // Initialize the collectiion cell based on the frame and add the tap gesture recognizer for custom animation - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; // Custom animation while tap the CollectionCell view. UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectedCellAnimation)]; [tapReconizer setNumberOfTouchesRequired : 1]; [tapReconizer setDelegate:self]; [self addGestureRecognizer:tapReconizer]; return self; } // Initialize the collection cell based on the nscoder and add the tap gesture recognizer for custom animation -(id) initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; // Custom animation while tap the CollectionCell view. UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectedCellAnimation)]; [tapReconizer setNumberOfTouchesRequired : 1]; [tapReconizer setDelegate:self]; [self addGestureRecognizer:tapReconizer]; return self; } // Initialize the collectiion cell and add the tap gesture recognizer for custom animation -(id) init { self = [super init]; // Custom animation while tap the CollectionCell view. UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectedCellAnimation)]; [tapReconizer setNumberOfTouchesRequired : 1]; [tapReconizer setDelegate:self]; [self addGestureRecognizer:tapReconizer]; return self; } // Customize the animation while tap the UICollectionViewCell with custom animation duration. - (void)selectedCellAnimation { [UIView animateWithDuration:0.4 delay:0 options:(UIViewAnimationOptionCurveEaseIn) animations:^{ CALayer *layer = self.layer; CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 25.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f); layer.transform = rotationAndPerspectiveTransform; } completion:^(BOOL finished) { [UIView animateWithDuration:0.3 delay:0 options:(UIViewAnimationOptionCurveEaseOut) animations:^{ CALayer *layer = self.layer; CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; rotationAndPerspectiveTransform.m24 = 0; rotationAndPerspectiveTransform =CATransform3DRotate(rotationAndPerspectiveTransform, 0.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f); layer.transform = rotationAndPerspectiveTransform; } completion:nil]; }]; } @end
- 在故事板中 - 添加带有单元标识符、UIImageView 和 UILabel 的 UICollectionViewCell。
- 将 UIImageView 和 UILabel 属性分配给 Storyboard 单元格。
在您的视图控制器中导入“UviCollectionCell.h”。
在 YourViewController.h 中
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath { UviCollectionCell *cell = (UviCollectionCell *) [cv dequeueReusableCellWithReuseIdentifier:@"collection_cell" forIndexPath:indexPath]; [cell.cellImageView setBackgroundColor: [UIColor randomColor]]; // You can add your image here. cell.cellImageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]]; [cell.cellTitle setText:[NSString stringWithFormat:@"S %ld - R %ld",(long)indexPath.section,(long)indexPath.row]]; //cell.backgroundColor = [UIColor randomColor]; return cell; }
UviCollectionCell.h
#import <UIKit/UIKit.h> @interface UviCollectionCell : UICollectionViewCell<UIGestureRecognizerDelegate> @property (strong, nonatomic) IBOutlet UIImageView *cellImageView; @property (strong, nonatomic) IBOutlet UILabel *cellTitle; @end
UviCollectionCell.m
#import "UviCollectionCell.h" @implementation UviCollectionCell // Initialize the collectiion cell based on the frame and add the tap gesture recognizer for custom animation - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; // Custom animation while tap the CollectionCell view. UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectedCellAnimation)]; [tapReconizer setNumberOfTouchesRequired : 1]; [tapReconizer setDelegate:self]; [self addGestureRecognizer:tapReconizer]; return self; } // Initialize the collection cell based on the nscoder and add the tap gesture recognizer for custom animation -(id) initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; // Custom animation while tap the CollectionCell view. UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectedCellAnimation)]; [tapReconizer setNumberOfTouchesRequired : 1]; [tapReconizer setDelegate:self]; [self addGestureRecognizer:tapReconizer]; return self; } // Initialize the collectiion cell and add the tap gesture recognizer for custom animation -(id) init { self = [super init]; // Custom animation while tap the CollectionCell view. UITapGestureRecognizer *tapReconizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectedCellAnimation)]; [tapReconizer setNumberOfTouchesRequired : 1]; [tapReconizer setDelegate:self]; [self addGestureRecognizer:tapReconizer]; return self; } // Customize the animation while tap the UICollectionViewCell with custom animation duration. - (void)selectedCellAnimation { [UIView animateWithDuration:0.4 delay:0 options:(UIViewAnimationOptionCurveEaseIn) animations:^{ CALayer *layer = self.layer; CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 25.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f); layer.transform = rotationAndPerspectiveTransform; } completion:^(BOOL finished) { [UIView animateWithDuration:0.3 delay:0 options:(UIViewAnimationOptionCurveEaseOut) animations:^{ CALayer *layer = self.layer; CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; rotationAndPerspectiveTransform.m24 = 0; rotationAndPerspectiveTransform =CATransform3DRotate(rotationAndPerspectiveTransform, 0.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f); layer.transform = rotationAndPerspectiveTransform; } completion:nil]; }]; } @end
回答by CouchDeveloper
In your code
在你的代码中
imageView.image = [UIImage imageNamed:[photoURLs objectAtIndex:indexPath.row]];
what does [photoURLs objectAtIndex:indexPath.row]
return?
哪些呢[photoURLs objectAtIndex:indexPath.row]
回报呢?
For use with imageNamed:
it MUST return a NSString
object which is the name of a resource located in the main bundle. It won't work with a URL, even less if this URL is pointing to a remote URL.
与imageNamed:
它一起使用必须返回一个NSString
对象,它是位于主包中的资源的名称。它不适用于 URL,如果此 URL 指向远程 URL,则更是如此。
Anyway, you shouldn't use imageNamed
. This method caches the image in the system's cache, which is not optimal/required in a collection/table view. Instead use an alternative method to create the UIImage
object.
无论如何,你不应该使用imageNamed
. 此方法将图像缓存在系统缓存中,这在集合/表视图中不是最佳/必需的。而是使用替代方法来创建UIImage
对象。
A solution to your problem depends whether you need to load your image data from a remote server or if these resources are located on the device.
问题的解决方案取决于您是否需要从远程服务器加载图像数据,或者这些资源是否位于设备上。
In the first case, you need an asynchronous approach in conjunction with a "placeholder image" which represents an image while being loaded when it is displayed in the cell.
在第一种情况下,您需要一种与“占位符图像”结合的异步方法,该“占位符图像”表示在单元格中显示时加载时的图像。
In the second case, you may use a simple synchronous approach to load images (similar to your existing solution, but using imageWithContentsOfFile:
for example), unless the images are large, in which case you need an asynchronous approach too.
在第二种情况下,您可以使用简单的同步方法来加载图像(类似于您现有的解决方案,但imageWithContentsOfFile:
例如使用),除非图像很大,在这种情况下您也需要异步方法。
Note: your code has a few other issues, too - but first and foremost you need to tell where your images come from.
注意:您的代码也有一些其他问题 - 但首先您需要知道您的图像来自哪里。
A possible (but not optimal) solution for loading images from the diskon the device:
从设备上的磁盘加载图像的可能(但不是最佳)解决方案:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"flickerCell";
FlickerCell* flickerCell = (FlickerCell*) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
flickerCell.backgroundColor = [UIColor whiteColor];
NSURL* url = [self.photoURLs objectAtIndex:indexPath.row]; // file URL
flickerCell.imageView.image = [UIImage imageWithContentsOfFile:[url path]];
return flickerCell;
}
A more sophisticated solution would loadand decodeimages aheadin a background thread - before they are actually displayed. That way, whenthey are actually displayed, the images are possibly already encoded and will render much faster. This also requires a cache.
更复杂的解决方案是在后台线程中提前加载和解码图像- 在它们实际显示之前。这样,当它们实际显示时,图像可能已经被编码并且渲染速度会快得多。这也需要缓存。