issue with identifiers using dequeueReusableCellWithReuseIdentifier - iphone

I'm getting this runtime error when I run my app in the simulator.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier PlayingCard - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
The line it crashes on is
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"PlayingCard"
forIndexPath:indexPath];
in the method
-(UICollectionViewCell*) collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{}
As I understand it, the error means the indentifier "PlayingCard" doesn' match up with any of the identifiers of CollectionViewCells in in the CollectionView, but I have made sure that the identifier in the storyboard is identical.
Thanks for your help

Your Error tell detail about your problem
must register a nib or a class for the identifier or connect a prototype cell in a storyboard
If you create UICollectionViewCell class only by code, use register class in viewDidLoad for collectionView
[self.collectionView registerClass:[YourCell class] forCellWithReuseIdentifier:#"PlayingCard"];
If you create UICollectionViewCell by Xib, use registerNib
If you drag UICollectionViewCell into storyboard, specify UICollectionView class and reuse identifier
I think you forgot to specify class name for your Cell in storyboard

Here is a sample code of how to implement the cell with identifier for uicollectionview. I hope this helps out
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"YourIdentifier" forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
Also there is a great tutorial on uicollectionview view in ray' web site that would help you understand the whole concept a bit more. Here is the link Tutorial
Edit:
The issue with your project crashing was indeed in the storyboard part. You did everything correctly but your cell was never connected. It was an easy fix. I sent you back the project and left you a bit comments in there too.

you should place
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell" ];
in your init or view did load as stated above and be sure that cell in story board has the same name.
your xml generated in your storyboard should look something like this (except collectionViewCell instead of tableViewCell)
<tableViewController id="qqN-Qz-7Na" customClass="ColorPickerSavedColorTableViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="jm9-vU-9fK" userLabel="TableView">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="8ty-Ap-v04">
<rect key="frame" x="0.0" y="22" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8ty-Ap-v04" id="Omv-J2-1dd">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
</tableView>
<navigationItem key="navigationItem" id="6MG-Do-Mu4"/>
</tableViewController>
look at the tableViewCell section

Related

Having trouble with CollectionView in Xcode - display's black screen

Basically I've been writing iOS apps for about 3 days (after reading a book to get the basic knowledge of design patterns and frameworks etc) and 1 entire day has been spent on this. I cannot get my CollectionView to display. I've got a storyboard that starts with a TabBarView and the two tabs (one is a TableView and the other is just a UIView) work, but the third tab (UICollectionView) just displays a black screen even after setting up.
How I set it up:
1) dragged a ViewController to the storyboard
2) made a relationship segue between my UITabBarController to the new ViewController
3) dragged a UICollectionView to the new ViewController
4) dragged 4 UICollectionViewCell's to the CollectionView
5) dragged 4 UILabels into said CollectionViewCell's
6) made a connection between the new CollectionView's delegate & data source and the header file of my CollectionView class (this might be where I went wrong, I did not make the connection to my ViewController.h class as I used this one for my UITableView and thought a new class was necessary)
7) declared the following methods in my CollectionView.m file
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//Populates each cell using the data given (no data in this case).
//Should return a CollectionViewCell.
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
return cell;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
//Gets the number of cells in each section.
//Should return an integer value.
return 2;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
//Tells the collection view the number of sections it should have.
//Should return an integer value.
return 4;
}
I get the feeling there is something I missed out, as this logic makes sense to me as a programmer but, having such little experience in Xcode, maybe I forgot to link up this class to my CollectionView or something. Does anybody know where I went wrong?
BTW in case you're wondering, I'm using this CollectionView more of a navigation technique than to display wonderful images or anything, I am going to populate them with generic images later when they actually show up in the emulator.
thanks
It is not displaying anything because default color of label is black, you'll have to change the color of text to any light color to see text over cell.
Now,
->Add a new file which should be subclass of UICollectionViewCell, Ctrl+drag from label to this class.(for eg I took mainViewCell)and label property name I took labelText
->Declare reuseIdentifier for cell from Attribute Inspector,(mainCell, I took)
->Import cellClass to your UIViewController Class,
->Using this method to display any text
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
mainViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"mainCell" forIndexPath:indexPath];
cell.labelText.text = #"What-ever-you-want-display";
return cell;
}
hope this would help...
Did you tell your view controller(the one that contains the collection view) to use UICollectionViewDelegateFlowLayout? For example,
#interface RootViewController () <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
Also, have you set the reuse identifier for your cell? In Interface Builder set this in the attributes inspector. Then go to the cellForItemAtIndexPath: method and change this line to use your identifier.
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
Check out UICollectionViewDelegateFlowLayout in the documentation for methods used to size cells and set margins and spacing.
The step 6) might be inadequate. Have you ctrl-dragged the collectionView to the controller icon beneath the main view directly? You would have been prompted in a black dialog box for connecting dataSource and delegate. The connections are made in XCode this way.
Alternatively you could explicitly set the dataSource as self in the controller implementation.
Remove registerClass code from the default view controller code snippet
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];

UICollectionView Custom Layout - Cells are not properly arranged

In my iPhone app,I want to use custom lay out in UICollectionview.There will different heights for Collection view cells.I want to set a lay out like that.
I tried many things and at last,made that height adjustment.(I am getting height for each object from server)
But the layout is not in a proper way.There are lots of spaces in between the items.
How can I achieve a proper layout.
Now I am getting a view like this
What I want is -
Here is my code -
-(CGFloat)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout heightForItemAtIndexPath:(NSIndexPath*)indexPath
{
return 60;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return array.count; // getting from server
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionCell" forIndexPath:indexPath];
cell.imageBG.image = [imagearray objectAtIndex:indexPath.item];
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize retval;
// I'm taking height of each images into HeightArray
retval = CGSizeMake(100, [[HeightArray objectAtIndex:indexPath.item]floatValue ]+50);
return retval;
}
From your screenshots it seems you are trying to use standard UICollectionViewFlowLayout (or its subclass). Unfortunately its limitation is that each row will always occupy the same height - it will be the same as in highest cell in that row, so you it is not suitable for your task and you have to implement your own layout.
Check UICollectionViewWaterfallLayout class which, although has its limitations (supports only 1 section, no decoration views) provides layout you need and at least can be a good starting point if you won't be able to use it as it is now.

how to reload supplementary view in collectionView

Is there an easy way to reload the suppplementary view only in a UICollectionViewFlowLayout? I don't want to reload the whole thing. Is it possible to do so?
After reviewing the documentation, I'm not sure about reloading an individual supplementary view, but you can use reloadSections: to update 1 or more sections in the UICollectionView. (documentation) So when a section header needs updating, you can call:
Objective-C:
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 3)]];
Swift:
self.collectionView?.reloadSections(IndexSet(0 ..< 3))
Which happens to call:
- (UICollectionReusableView *)collectionView: (UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
//Place logic for handling update here...
}
If you want to change the layout or size of the supplementary view from the Controller, use[self.collectionView.collectionViewLayout invalidateLayout].If you want to refresh the supplementary view only,use [supplementaryView setNeedsDisplay].Use both if the supplementary view is complex and/or will change its dimensions.

UITextField artifacts

I have an iPhone app which has a Table View-based data input screen with a toggle, which when on shows all rows in another section of the table.
Sometimes, when the app is first loaded, and usually when it has been fully deleted from the phone, the UITextFields from the original section of the table are displayed in addition to the new rows, as below (main table section is above)
:
THe strangest thing about this is that this behaviour only occurs the first time this screen is displayed - it seems fine after that. Oh, and it only seems to occur on the phone, not the simulator.
Given the random nature of this, could it have something to do with other apps? I did have apps with similar namespaces running at the same time. The problem seemed to go away after I closed the apps down / deleted from phone.
I have included the code block that is run when the switch is changed below:
- (void)accountSwitchChanged {
[customerDetails saveField:#"addToAccount" WithBool:addToAccountSwitch.on];
NSArray *indexes = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:1 inSection:1], [NSIndexPath indexPathForRow:2 inSection:1], [NSIndexPath indexPathForRow:3 inSection:1],nil];
if (addToAccountSwitch.on)
[detailsTable insertRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationFade];
else
[detailsTable deleteRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationFade];
}
Any ideas?
--EDIT
cellForRowAtIndexPath code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// get rid of grey background for iPad app
[tableView setBackgroundView:nil];
UITableViewCell *cell = nil;
NSDictionary *cellData = [[dataSourceArray objectAtIndex: indexPath.section] objectAtIndex:indexPath.row];
id cellControl = [cellData objectForKey:kCellControlKey];
static NSString *kCellControl = #"CellControl";
cell = [tableView dequeueReusableCellWithIdentifier:kCellControl];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellControl] autorelease];
cell.textLabel.textColor = [[[ConfigManager sharedInstance].skin valueForKey:#"tableCellHeadingTextColour"] toUIColor];
cell.backgroundColor = [[[ConfigManager sharedInstance].skin valueForKey:#"tableCellBgColour"] toUIColor];
cell.textLabel.font = [UIFont boldSystemFontOfSize:17];
} else {
// a cell is being recycled, remove the old control (if it contains one of our tagged edit fields)
UIView *viewToCheck = nil;
viewToCheck = [cell.contentView viewWithTag:kDetailsViewTag];
if (!viewToCheck)
[viewToCheck removeFromSuperview];
}
// if control is not a text field, make it a button
if (![cellControl isKindOfClass:[UITextField class]])
cell.selectionStyle = UITableViewCellSelectionStyleGray;
else
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = [cellData objectForKey:kCellTitleKey];
[cell.contentView addSubview:cellControl];
return cell;
}
Something to check and eliminate If it is only occurring the first time view is displayed, it's always worth checking whether you are assuming the view is loaded before you are doing work on it. This doesn't come up very often, but when it does it can be very hard to track down. To check whether this might be your issue, add a [viewController view] call just after you create the view for the first time. This forces the view to be loaded. If the issue goes away when you add this, you've tracked the source of the issue. And you can even leave the [viewController view] call in as a fix, or work through your code to allow for lazy instantiation.
All this said, far more likely to be something funny in your tableView:cellForRowAtIndexPath: code. If you want good stack overflow, post all or relevant fragment of the that code (or the relevant code it calls).
Follow up on posted code:
(1) if (!viewToCheck) [viewToCheck removeFromSuperview] won't do anything. It'll only send a removeFromSuperview message when viewToCheck is nil and that won't do anything. Not sure if this will be key issue, but it's something to put right.
(2) [cell.contentView addSubview:cellControl]; - this looks problematic - it's usually best to only add subviews when you create the cell. You can hide or show in the main body of tableView:cellForRowAtIndexPath: - that would, I suspect, work for you here. With this code there's a risk here that you'll either add multiple subviews when you only want one or (which may be what's going on here) that you end up not removing a subview when a cell is recycled. If the viewToCheck code is supposed to be removing the added cellControl then, as (1), it won't do that just now because your if condition is wrong.

New YouTube iframe code not displaying video on iPhone

We added the new YouTube iframe code into our News site. The problem is the video doesn't appear on the iPhone.
Here's my page and code:
<iframe width="620" height="390" src="http://www.youtube.com/v/A2V1WTF8tp4?hl=en&fs=1&autoplay=0&hd=1" frameborder="0" allowfullscreen="true"></iframe>
How can I get YouTube video to appear on the iPhone?
The URL for the video might be the problem. The embedded video code goes like this
<iframe class="youtube-player" type="text/html" width="640" height="385" src="http://www.youtube.com/embed/VIDEO_ID" frameborder="0">
</iframe>
Notice how the URL uses embed instead of v.
Your problem may be that YouTube is Flash based, so embedding an iframe isn't going to work on the iPhone, which doesn't support Flash.
Try something like this instead:
<object type="application/x-shockwave-flash" data="http://www.youtube.com/v/A2V1WTF8tp4?hl=en&fs=1&autoplay=0&hd=1" width="620" height="3900">
<param name="movie" value="http://www.youtube.com/v/A2V1WTF8tp4" />
<param name="quality" value="high" />
<param name="allowFullScreen" value="true" />
<!-- Fallback content -->
<a href="http://www.youtube.com/watch?v=A2V1WTF8tp4">
<img src="http://img.youtube.com/vi/A2V1WTF8tp4/0.jpg" width="620" height="390" alt="Staff Gathers for Multicultural Springfest" />
</a>
</object>
code courtesy of: http://learningtheworld.eu/2009/youtube-embed/
I have a subclass of UIWebView to accomplish this, and this is how it works:
(in init:)
NSString* url = [NSString stringWithFormat: #"http://www.youtube.com/embed/A2V1WTF8tp4"];
CGRect theFrame = CGRectMake(0, 0, 400, 300);
NSString* embedHTML = [NSString stringWithFormat: #"<iframe width=%i height=%i src=%# frameborder=10 allowfullscreen></iframe>", theFrame.size.width, theFrame.size.height, url];
[self loadHTMLString: embedHTML baseURL: nil]; // this method is part of UIWebView.
Just ensure your "video view" is added as a subview of whichever view owns it.