如何将 UIImages 数组添加到集合视图
Posted
技术标签:
【中文标题】如何将 UIImages 数组添加到集合视图【英文标题】:How to Add an Array of UIImages to a Collection View 【发布时间】:2013-08-01 18:13:10 【问题描述】:提前感谢您查看此项目并帮助我。
故事板连接
我试图在我的集合视图中显示一组 UIImages。我已经连接了故事板中的所有内容。 我的 ViewController 是我的 Collection View 的委托和数据源。 我的单元格包含一个 UIImageView,它在我的自定义单元格的头文件中有一个 IBOutlet。
应用目前的工作原理
-
应用程序根据*** API 创建一组图像
按用户搜索。
一旦用户输入他或她的搜索,ViewController 就会通过
NSString 关闭模型(GetImageURL.h 和 GetImageURL.m.)
这似乎基于我正在使用的 NSLogs 工作。
模型一旦设置了一个
UIImages 数组。
ViewController 然后尝试重新加载 collectionView 的数据并
应用崩溃。
错误信息如下所示:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'
*** First throw call stack:
(0x1c97012 0x10d4e7e 0x1c96deb 0x518748 0x533b1b 0x533646 0xf9ff8 0xfa232 0x5338d5 0x29a4 0x3ef6 0xb13fb4 0xb13e67 0x30ca 0x49fb53f 0x4a0d014 0x49fd7d5 0x1c3daf5 0x1c3cf44 0x1c3ce1b 0x1bf17e3 0x1bf1668 0x18ffc 0x1b9d 0x1ac5)
libc++abi.dylib: terminate called throwing an exception
我的问题
我想知道我在创建 collectionView 时做错了什么,导致它在稍后调用 reloadData 时崩溃。
代码
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UICollectionViewController <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UIApplicationDelegate>
//receives a mutable array of UIImage(s)
-(void)receiveArrayOfImages: (NSMutableArray *)arrayOfImages;
@end
视图控制器.m
#import "ViewController.h"
#import "Cell.h"
#import "GetImageURL.h"
NSString *kCellID = @"cellID";
@interface ViewController ()
UISearchBar *searchBar;
@property (nonatomic, strong) NSString *searchBarText;
@property (strong, nonatomic) NSMutableArray *arrayOfImages;
@end
@implementation ViewController
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
if ([self.arrayOfImages count] > 0)
NSLog(@"return %d items for collection view", [self.arrayOfImages count]);
return [self.arrayOfImages count];
else
NSLog(@"returned 0 items for collection view");
return 0;
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
NSLog(@"cellForItemAtIndexPath");
Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
int row = [indexPath row];
cell.cellImage.image = [self.arrayOfImages objectAtIndex:row];
return cell;
- (void)viewDidLoad
[super viewDidLoad];
//Creates a Search Bar Button System Item.
UIBarButtonItem *searchButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:@selector(tapSearchButton:)];
self.navigationItem.rightBarButtonItem = searchButton;
-(void)tapSearchButton:(id)sender
//Adds or takes away searchbar on navigationbar.
if (!searchBar)
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(-5.0, 0.0, 320.0, 44.0)];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
UIView *searchBarView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 310.0, 44.0)];
searchBarView.autoresizingMask = 0;
searchBar.delegate = self; //this line causes a warning. "Assigning to 'id<UISearchBarDelegate> from incompatible type 'ViewController *cons_strong"
[searchBarView addSubview:searchBar];
self.navigationItem.titleView = searchBarView;
[searchBar becomeFirstResponder];
else
self.navigationItem.titleView = nil;
searchBar = nil;
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
GetImageURL *bookName = [[GetImageURL alloc] init];
bookName.bookName = [searchBar text]; //this line causes a warning. "Local declaration of 'searchBar' hides instance variable"
NSLog(@"In ViewController, the book name is: %@", bookName.bookName);
[bookName recieveBookUrl:bookName.bookName];
[self.view endEditing:YES];
-(void)receiveArrayOfImages: (NSMutableArray *)arrayOfImages
//receives an array of UImages called arrayOfImages and sets it to self.arrayOfImages
self.arrayOfImages = arrayOfImages;
NSLog(@"This is the array of UIimages in ViewController.m: %@", self.arrayOfImages);
[self.collectionView reloadData]; //This line causes the app the crash. "Reason: UICollectionView must be initialized with a non-nil layout parameter"
@end
细胞.h
#import <UIKit/UIKit.h>
@interface Cell : UICollectionViewCell
//UIImageView inside Custom Cell
@property (strong, nonatomic) IBOutlet UIImageView *cellImage;
@end
细胞.m
#import "Cell.h"
@implementation Cell
- (id)initWithCoder:(NSCoder *)coder
self = [super initWithCoder:coder];
if (self)
return self;
@end
GetImageURL.h
#import <Foundation/Foundation.h>
#import "ViewController.h"
@interface GetImageURL : NSObject
@property (strong, nonatomic) NSString *bookName;
@property (strong, nonatomic) NSMutableArray *imageArray;
-(void)recieveBookUrl:(NSString *)bookName; //recieves a string from the viewController that the user inputs
@end
GetImageURL.m
#import "GetImageURL.h"
@interface GetImageURL()
@property (strong, nonatomic) NSString *pageID;
@property (strong, nonatomic) NSMutableArray *imageUrlArray;
@end
@implementation GetImageURL
//takes the string that the user entered and alters it to fit the wikipedia API format
-(void)recieveBookUrl:(NSString *)bookName
self.imageUrlArray = [[NSMutableArray alloc] init];
self.imageArray = [[NSMutableArray alloc] init];
bookName = [bookName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //or use string by replacing @" " with @"%20";
NSString *wikiAPI = @"http://en.wikipedia.org/w/api.php?format=json&indexpageids&action=query&prop=images&titles=";
bookName = [wikiAPI stringByAppendingString:bookName];
NSURL *bookURL = [NSURL URLWithString:bookName];
//Plan to put this action in the background later
dispatch_async(dispatch_get_main_queue(), ^()
NSData *data = [NSData dataWithContentsOfURL:bookURL];
[self performSelectorOnMainThread:@selector(getBookTitleApi:) withObject:data waitUntilDone:YES];
);
//first part of the API sucessfully gets the padeID and all the images returned by the API.
-(void)getBookTitleApi: (NSData *)data
NSError *error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
NSDictionary *parseQueryBookTitle = [json objectForKey:@"query"];
NSArray *parsePageIdsBookTitle = [parseQueryBookTitle objectForKey:@"pageids"];
for (NSDictionary *pageIdBookTitle in parsePageIdsBookTitle)
self.pageID = [NSString stringWithFormat:@"%@", pageIdBookTitle];
NSDictionary *parsePagesBookTitle = [parseQueryBookTitle objectForKey:@"pages"];
NSDictionary *parsePageIdBookTitle = [parsePagesBookTitle objectForKey:self.pageID];
NSDictionary *parseImagesBookTitle = [parsePageIdBookTitle objectForKey:@"images"];
NSDictionary *valueTitleBookTitle = [parseImagesBookTitle valueForKey:@"title"];
for (NSDictionary *imageFilenames in valueTitleBookTitle)
NSString *imageFilename = [NSString stringWithFormat:@"%@", imageFilenames];
imageFilename = [imageFilename substringFromIndex:5];
imageFilename = [imageFilename stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //or use string by replacing @" " with @"%20";
NSString *wikiImageAPI = @"http://en.wikipedia.org/w/api.php?action=query&format=json&indexpageids&prop=imageinfo&iiprop=url&titles=Image:";
imageFilename = [wikiImageAPI stringByAppendingString:imageFilename];
NSURL *imageFilenameUrl = [NSURL URLWithString:imageFilename];
NSData *data = [NSData dataWithContentsOfURL:imageFilenameUrl];
[self performSelectorOnMainThread:@selector(getImageApi:) withObject:data waitUntilDone:YES];
//Uses the URLs to create an NSData object and then uses that data to create a UIImage which is added to a Mutable Array
for (NSString *jpgURL in self.imageUrlArray)
NSURL *imageURL = [NSURL URLWithString:jpgURL];
NSLog(@"This is an imageURL in GetImageURL.m: %@", imageURL);
NSData *data = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:data];
[self.imageArray addObject:image];
NSLog(@"The array of images in GetImageURL.m contains %d images called %@", [self.imageArray count], self.imageArray);
ViewController *view = [[ViewController alloc] init];
[view receiveArrayOfImages:self.imageArray]; //sends the array of images to the View Controller
//objects removed from array so that next user search can start over
[self.imageArray removeAllObjects];
[self.imageUrlArray removeAllObjects];
//Uses the image filenames from the first section and gets the specific URLS for the image. Limits results to .jpg images
-(void)getImageApi: (NSData *)data
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSDictionary *parseQueryImage = [json objectForKey:@"query"];
NSDictionary *parsePageIdsImage = [parseQueryImage objectForKey:@"pageids"];
for (NSString *pageIdImage in parsePageIdsImage)
NSDictionary *parsePagesImage = [parseQueryImage objectForKey:@"pages"];
NSDictionary *parsePageIdImage = [parsePagesImage objectForKey:pageIdImage];
NSDictionary *parseImageInfoImage = [parsePageIdImage objectForKey:@"imageinfo"];
NSDictionary *valueImageInfoUrlsImage = [parseImageInfoImage valueForKey:@"url"];
for (NSString *valueImageInfoUrlImage in valueImageInfoUrlsImage)
if ([valueImageInfoUrlImage hasSuffix:@".jpg"])
[self.imageUrlArray addObject:valueImageInfoUrlImage];
@end
抱歉把所有的代码都放在这里了。我想如果一切都在那里,那会更容易。也许它对其他人也有帮助。
谢谢!
【问题讨论】:
这可以帮助***.com/a/17856406/1305001 【参考方案1】:您的布局设置为流畅吗?它在您的 Storyboard 中应该如下所示:
如果您将其设置为自定义,则需要自己创建布局。
【讨论】:
我没有更改任何设置,除了为我的单元分配正确的类并更改它的reuseID。感谢您的帮助!【参考方案2】:如果您的集合视图单元不是在情节提要中创建的,那么我认为您必须注册它。
如果你的细胞被编程了
// Add this in your controller's viewDidLoad method
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kCellID];
如果你的单元格有一个 nib 文件,我认为它是 registerNib:forCellWithReuseIdentifier:
【讨论】:
感谢您的评论。我正在使用我在某处读过并尝试过的原型单元,它包含在情节提要中的集合视图控制器中。以编程方式制作单元会更好吗?我在 Apple 的文档中找到了 registerClass:,但它没有帮助,所以我把它拿出来了。还有其他想法吗?再次感谢您的帮助。【参考方案3】:-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
return array.count;
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
static NSString *identifier = @"Cell";
UIImage *smallimage = [UIImage imageNamed:[NSString StringWithFormat:@"%@.png"[array[indexpath]]];
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *gridimageview = (UIImageView *)[cell viewWithTag:100];
[gridimageview setImage:smallimage];
return cell;
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
NSLog(@"index path is %d", indexPath.row);
//Enter the action you want when an image is clicked in collection view
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
// Write your code here to deselect the selected image
【讨论】:
感谢您的回复。我的代码有点麻烦,尽管我同意 cellForItemAtIndexPath: 可能是我的问题。我在创建 UIImage *small 图像以及下面的行时遇到错误。另外,如果我的数组已经包含 UIImage,我是否需要创建另一个 UIImage?再次感谢您的帮助! 现在试试这段代码并检查你是否在故事板的collectionviewcell中为你的imageview设置了一个标签为100。数组[indexpath]也使用你的数组名称。 我在情节提要中将单元格的标签设置为 100,并用 self.arrayOfImages 替换了“array[indexpath]。应该是 self.arrayOfImages[indexPath]?我收到一条错误消息UICollectionView 必须使用非零布局参数进行初始化。 你需要在你的故事板上为集合视图控制器设置一个标识符,否则它不会返回任何东西 在 Collection View Controller 的身份检查器中,我将故事板 ID 和恢复 ID 设置为 collectionViewController。我需要在我的代码中的某个地方使用它吗?以上是关于如何将 UIImages 数组添加到集合视图的主要内容,如果未能解决你的问题,请参考以下文章