如何将UIImages数组添加到集合视图

时间:2013-08-01 18:13:10

标签: ios objective-c uicollectionview

提前感谢您查看此项目并向我伸出援助之手。

故事板连接

我正在尝试在Collection View中显示一组UIImages。我已连接故事板中的所有内容。
我的ViewController既是我的Collection View的委托和dataSource。
我的单元格包含一个UIImageView,它在我的自定义单元格的头文件中有一个IBOutlet。

应用目前如何运作

  1. 该应用程序基于a从维基百科API创建一系列图像 用户搜索。
  2. 一旦用户输入他或她的搜索,ViewController就会通过 NSString关闭到模型(GetImageURL.h和GetImageURL.m。)
  3. 这似乎是基于我正在使用的NSLog。
  4. 模型设置完成后,模型会将其传回控制器 UIImages数组。
  5. ViewController然后尝试重新加载collectionView的数据和 应用程序崩溃。
  6. 错误消息如下所示:

    *** 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
    


    ViewController.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
    


    Cell.h

    #import <UIKit/UIKit.h>
    
    @interface Cell : UICollectionViewCell
    
    //UIImageView inside Custom Cell
    @property (strong, nonatomic) IBOutlet UIImageView *cellImage;
    
    @end
    


    Cell.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
    


    很抱歉在这里转储所有代码。我认为如果它就在那里会更容易。也许它对别人也有帮助。

    谢谢!

3 个答案:

答案 0 :(得分:0)

您的布局是否设置为流量?它应该在你的故事板中看起来像这样:

Collection view layout screenshot

如果将其设置为自定义,则需要自己创建布局。

答案 1 :(得分:0)

如果您的集合视图单元格未在故事板中创建,那么我认为您必须注册它。

如果您的细胞已编程

// Add this in your controller's viewDidLoad method
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kCellID];

如果您的单元格有一个nib文件,我认为它是registerNib:forCellWithReuseIdentifier:

答案 2 :(得分:-1)

-(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
    }
}