Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to Add an Array of UIImages to a Collection View
    primarykey
    data
    text
    <p>Thanks in advance for checking out this project and lending me a hand.<br></p> <h2>Storyboard Connections</h2> <p>I am trying to display an array of UIImages in my Collection View. I have connected everything in the storyboard. <br> My ViewController is both the delegate and dataSource for my Collection View. <br> My cell contains a UIImageView that has an IBOutlet in my custom cell's header file.<br><br></p> <h2>How the App Currently Works</h2> <ol> <li>The App creates an array of images from the wikipedia API based on a search by a user.</li> <li>Once the user types in his or her search, the ViewController passes the NSString off to the model (GetImageURL.h and GetImageURL.m.)</li> <li>This seems to be working based off the NSLogs that I am using.</li> <li>The Model passes it back to the controller once it has set up an array of UIImages.</li> <li>The ViewController then attempts to reload the collectionView's data and the app crashes.</li> </ol> <p>The error message looks like this:</p> <pre><code>*** 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 </code></pre> <p><br></p> <h1>My Question</h1> <p>I am wondering what I am doing wrong to create collectionView that causes it to crash upon a call later to reloadData. <br></p> <h1>Code</h1> <p>ViewController.h</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @interface ViewController : UICollectionViewController &lt;UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UIApplicationDelegate&gt; //receives a mutable array of UIImage(s) -(void)receiveArrayOfImages: (NSMutableArray *)arrayOfImages; @end </code></pre> <p><br> ViewController.m</p> <pre><code>#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] &gt; 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&lt;UISearchBarDelegate&gt; 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 </code></pre> <p><br> Cell.h</p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @interface Cell : UICollectionViewCell //UIImageView inside Custom Cell @property (strong, nonatomic) IBOutlet UIImageView *cellImage; @end </code></pre> <p><br> Cell.m</p> <pre><code>#import "Cell.h" @implementation Cell - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { } return self; } @end </code></pre> <p><br> GetImageURL.h</p> <pre><code>#import &lt;Foundation/Foundation.h&gt; #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 </code></pre> <p><br> GetImageURL.m</p> <pre><code>#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&amp;indexpageids&amp;action=query&amp;prop=images&amp;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:&amp;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&amp;format=json&amp;indexpageids&amp;prop=imageinfo&amp;iiprop=url&amp;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:&amp;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 </code></pre> <p><br></p> <p>Sorry for dumping all the code in here. I figured it would be easier if it was all there. Maybe it will be helpful to someone else too.</p> <p>Thanks!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload