Error returning integer as number of items in section - objective-c

I have an iPad app, using Storyboards, Tab Bar and XCode 4.5. One of my scenes has a UITableView in the upper left quadrant, with labels and UITextBoxes in the right upper quadrant.
When I click on the second tab, I am taken to the scene described above. This is the code:
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[Cell class] forCellWithReuseIdentifier:#"MY_CELL"];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 4;
}
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
return 4;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"MY_CELL" forIndexPath:indexPath];
cell.label.text = [NSString stringWithFormat:#"%d",indexPath.item];
return cell;
}
This is the interface definition:
#interface ClientViewController : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource> {
}
This is the error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView
collectionView:numberOfItemsInSection:]: unrecognized selector sent to
instance 0x7d925b0'
As you see, I used the same code for numberOfSectionsInCollectionView. I have researched SO and Google and found nothing that applies.
What am I doing wrong?

There are two delegates to set. One is the delegate, and one is the dataSource. Generally, both should be set to point to your view controller (ie, self in most circumstances).

Related

Collection View didSelectItemAtIndexPath segue

I'm struggling for a long time of this problem.
The reason was I had Collection delegate & datasource under the "CollectionView" not "CollectionView Controller" because I embedded one collectionView in the one of TableView Cell
but when I want to set up the
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)
{
}
This is my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * Cell;
if (indexPath.section==0)
{
switch (indexPath.row)
{
case 0:
Cell = #"MoviesIntro";
break;
case 1:
Cell = #"影片介紹";
break;
case 2:
Cell = #"Moviesrelative";
default:
break;
}
}
 
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:Cell];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Cell];
}
switch (indexPath.row)
{
case 0:
{
}
break;
case 1:
{
}
break;
case 2:
{
Tony=(CollectionView*)[cell viewWithTag:741];
Tony.pageImages =imagearray;
[Tony reloadData];
}
break;
default:
break;
}
return cell;
}
Here is CollectionView.m Code
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
self.pic_url=[comment[indexPath.row] objectForKey:#"pic_url"];
self.name_zh=[comment[indexPath.row] objectForKey:#"name_zh"];
self.name_en=[comment[indexPath.row]objectForKey:#"name_en"];
self.intro=[comment[indexPath.row] objectForKey:#"short_Intro"];
self._id=[comment[indexPath.row] objectForKey:#"_id"];
self.trailer=[comment[indexPath.row] objectForKey:#"trailer"];
self.movieTime=[comment[indexPath.row] objectForKey:#"movieTime"];
self.picH_url=[comment[indexPath.row] objectForKey:#"picH_url"];
self.category=[comment[indexPath.row] objectForKey:#"category"];
self.director=[comment[indexPath.row] objectForKey:#"director"];
self.actor=[comment[indexPath.row] objectForKey:#"actor"];
self.language=[comment[indexPath.row] objectForKey:#"language"];
self.MyList=false;
[UIView animateWithDuration:0.05 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
} completion:^(BOOL finished) {
}];
}
Tony is Collection view.h/m files. pageImages is NSMutableArray on the Tony.h files.
to go to other view controller, property not found on object so I don't even know what can i do is anyone have good idea??
You can set add a delegate variable of your UITableViewCell and a delegate method like:
- (void) pushToViewController;
Then in YourTableViewCell.m file collectionView delegate methods add:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *){
[delegate pushToViewController];
}
And "tableView Controller"should be the delegate of your tableViewCell, in the controller of UITableView :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
YourTableViewCell *cell = ...
cell.delegate = self;
}
- (void) pushToViewController {
[self.navigationController pushViewController:someViewController animated:YES];
}
William Hu's suggestion will work.
In general you should not let your UI items implement their own delegates and data sources. It works but breaks the MVC pattern. Instead of that I'd use some custom UICollectionView to hold some reference to the row of the table to which it belongs. You could even 'abuse' the tag property for that (which I personally don't like but is is quite a common pattern) without the need to subclass UICollectionView.
Your UITableViewController can implement the datasource and delegate for the collection views too. On each call of any delegate method a reference to the very collectionView is handed into the method so that you can get the row of the table from there (which you have to set in the table view's cellForRowAtIndexPath of course) and go from there.
Therefore I'd rather suggest re-factoring your code and stick to the MVC pattern.

UICollectionView crashes randomly because of highlighting issue

I have a UICollectionView on iOS7 which crashes randomly when intense scrolling. I enabled zombies and found that it gives me an error saying:
*** -[NSIndexPath section]: message sent to deallocated instance 0x17dbc970
I believe this is due to an Apple error described here. Apparently, the app crashes when someone highlights a cell while scrolling fast, and then the OS tries to unhighlight it when it moves off screen, when it ceases to exist. The proposed solution is to disable the userInteractionEnabled property of the cell and then handle the selection using UIGestureRecogniser.
Has anyone else faced this same issue? Also, I tried unsetting the userInteractionEnabled property and using a gesture recogniser, but this doesn't seem to work. Any idea how I can fix this?
EDIT: Code added on request
-(UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifier = #"Gallery_Cell";
GalleryCell *cell= (GalleryCell *)[self.flowCollection dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
if (indexPath.row < self.collectionData.count) {
CellDetails *dets = [self.collectionData objectAtIndex:indexPath.row];
NSURL *mainImageURL = [NSURL URLWithString:dets.imageURL];
cell.image.contentMode = UIViewContentModeScaleAspectFill;
cell.image.clipsToBounds = YES;
if ([[[SDWebImageManager sharedManager] imageCache] imageFromDiskCacheForKey:[self cacheKeyForURL:mainImageURL]] == nil) {
[cell.image setImageWithURL:mainImageURL placeholderImage:nil];
}else{
[cell.image setImage:[[[SDWebImageManager sharedManager] imageCache] imageFromDiskCacheForKey:[self cacheKeyForURL:mainImageURL]]];
}
}
return cell;
}
EDIT: more code..
I defined the GalleryCell for reuse as follows:
[self.flowCollection registerNib:[UINib nibWithNibName:#"Thumbs_Cell" bundle:nil] forCellWithReuseIdentifier:#"Gallery_Cell"];
The GalleryCell class implementation is:
GalleryCell.h
#interface GalleryCell : UICollectionViewCell
#property (nonatomic, retain) IBOutlet UIImageView *image;
#end
GalleryCell.m
#implementation GalleryCell
#synthesize image;
-(void) setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}
-(void)prepareForReuse {
[super prepareForReuse];
[self.image cancelCurrentImageLoad]; // SDWebImage method to cancel ongoing image load
}
OK. I seem to have solved it. In case anyone faces this problem, here is the fix:
I implemented the following method in my UICollectionViewDelegate:
-(BOOL) collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
This prevents any cell from highlighting, and hence, avoids the crash when the system tries to unhighlight it when it goes off-screen. But, when you do this it also stops calling the didSelectItemAtIndexPath method. So I had to use a UITapGestureRecogniser method to implement cell selection instead.
Hope this helps.
I would suggest returning the following:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath{
return !collectionView.dragging && !collectionView.tracking;
}

unable to dequeue a cell with identifier tag

I'm getting an error when a button press loads the class posted below.
The code is supposed to load a slide out menu. This is the line that is causing my issues. I'm completely new to iOS / obj-c. I'm not sure why, but the method this line of code is in, loops through for each entry in the _menuItems array? The NSLog outputs for each item of the array, but then it runs another time and throws this error? Thats what I think is happening at least. If anyone could give me some pointers, I'd be grateful. Aside to all that, my project has two targets - I don't know why, I don't know how, and I don't know how to change it. Could that be the issue?
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
The console printout is this:
013-11-28 12:11:31.902 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.908 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.911 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.917 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.921 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.924 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.929 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.931 DatabaseTest[57858:a0b] The code runs through here!
2013-11-28 12:11:31.932 DatabaseTest[57858:a0b] *** Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:5261
2013-11-28 12:11:31.936 DatabaseTest[57858:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier tag - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
.
#import "SidebarViewController.h"
#import "SWRevealViewController.h"
#interface SidebarViewController ()
#property (nonatomic, strong) NSArray *menuItems;
#end
#implementation SidebarViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithWhite:0.2f alpha:1.0f];
self.tableView.backgroundColor = [UIColor colorWithWhite:0.2f alpha:1.0f];
self.tableView.separatorColor = [UIColor colorWithWhite:0.15f alpha:0.2f];
_menuItems = #[#"title", #"news", #"comments", #"map", #"calendar", #"wishlist", #"bookmark", #"tag"];
}
- (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender
{
// Set the title of navigation bar by using the menu items
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
destViewController.title = [[_menuItems objectAtIndex:indexPath.row] capitalizedString];
if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: #[dvc] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
};
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#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.menuItems count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [self.menuItems objectAtIndex:indexPath.row];
NSLog(#"The code runs through here!");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
#end
You must use
static NSString *CellIdentifier = #"messageCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Do not use if your cell is not registered a class or nib with Cell ID;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
Apple Documentation:
Important
You must register a class or nib file using the registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier: method before calling this method.
Edited:
This is wrong:
NSString *CellIdentifier = [self.menuItems objectAtIndex:indexPath.row];
Unless you have registered a cell for each row this isn't going to work.
You need to use a cell identifier that has been registered either in code or from the storyboard / xib.
also - the way you are doing this now takes no advantage of cell reuse if each cell loads a cell with a unique identifier.
I am not sure if you still after the answer for this question, but if you are here is the way you could solve your problem.
Your problem arises from the fact that the cell hasn't got an identifier or if it does, the identifier doesn't match the code in the NSArray *menuItems. To solve the problem:
you should go to the Document Outline (The small arrow at the bottom left of your storyboard)
then you should click on the 'Table View Cell - tag. (It should highlight the cell 'Tag'
Go to the Attributes Inspector and find 'Identifier'
Finally, change or ad the Identifier name, in your case 'tag'.
Et voila!, that should do the trick
Beware of spelling as Objective C is very tight on spelling, I mean you have to make sure the same way you spell the identifier, you must use the same spelling in your code.
Hope that help,
See picture: (I wanted to post one for you, but it seems like I cannot do so, Ooops!)

UICollectionView cellForRow Crash

Hello I am having trouble getting a custom object at the index path of the UICollectionView...
Below is my code.
I am getting the crash
[Player firstName:]: unrecognized selector sent to instance
Any suggestions?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
BenchCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CollectionCell forIndexPath:indexPath];
[cell setFrame:CGRectMake(0, 4, 120, 50)];
Player*homeBenchPlayer = [[self homeBench]objectAtIndex:indexPath.row];
cell.playerName.text = homeBenchPlayer.firstName;
cell.playerPosition .text = homeBenchPlayer.position;
cell.playerPicture.image = [ UIImage imageWithData:homeBenchPlayer.picture];
return cell;
}
When I get this error unexpectedly I usually return to IB, select the object responsible for the crash, and investigate the Connections Inspector. Generally the problem seems to be an incorrect referencing outlet or sent event.
This could be caused by calling performSelector:#selector(dismissModal:) where the callee doesn't exist.

UICollectionView cellForItemAtIndexPath not registering cell

I am trying to use UICollectionViewCell, since all I want to display is an image. I can add the image to the cell using UIColor colorWithImage: on the UICollectionViewCell's contentView property.
In my loadView method, I am registering the cell as follows:
[self.collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:#"MyCell"];
Below is my cellForItemAtIndexPath method:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
// cell customization
return cell;
}
When I run it, as soon as it hits the dequeue line, it crashes with the following error:
*** Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:]
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier MyCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
I tired setting up a custom cell, and used it as the class and I got the same error. My custom cell subclassed UICollectionViewCell and had nothing implemented, except for the default initWithFrame. That is because I wanted to just change the background colour of the view. I am not sure what the problem is but could someone please take a look at my code and help me? I've been trying to figure this out for quite a while with absolutely no luck at all.
If you just want to display an image, you don't need to do any subclassing, you can set the cell's backgroundColor with colorWithPatternImage:. Register the class like this:
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"Cell"];
Then use it like so:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithPatternImage:[self.results objectAtIndex:indexPath.row]];
return cell;
}
In this example, results is an array of UIImages.
If you are using xib in applivation then add following in your viewdidLoad method
[self.myCollectionView registerNib:[UINib nibWithNibName:#"CollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"CellIdentifier"];
otherwise If you using storyboard add following
[self.myCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"CellIdentifier"];
Finally add this (If not)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CellIdentifier" forIndexPath:indexPath];
return cell;
}
Hope above will help.
Try setting a breakpoint on
[self.collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:#"MyCell"];
I would guess your loadView (did you mean viewDidLoad?) method is not being called, so the class is never registered with the collectionView.
if your collection view is connected on storyboard and the delegate and datasource is set there, and you provide the necessary methods for the datasource and delegate, then adding the register call makes the
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
return a UICollectionView instead of your own subclass of it. So do either but not both.
set your cell identifier name as in code