I was using awakeFromNib to set an image with this code
self.cellImage01 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"mushroom_risotto.jpg"]];
self.cellImage01.frame = CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height);
self.cellImage01.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.cellImage01.contentMode = UIViewContentModeScaleAspectFit;
Then I needed indexPath to get the image info from it's data source so I moved the code from awakeFromNib to cellForItemAtIndexPath. Now it displays differently
it doesn't have the same scaleAspectFit
going to landscape changes it to a small slice of the pic.
The small slice image only happens when the cell goes out of view, then back into view.
I'm using cell reuse and that seems to be where things are changing, but I can't access the code for that to see what's going on.
Does anyone know the call stack it goes thru for cell reuse?
Why would the aspect work in awakeFromNib and not in cellForItemAtIndexPath?
The common element here is that cellForItemAtIndexPath calls this first:
ArticleCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ArticleCollectionViewCell" forIndexPath:indexPath];
Edit: I should have noted that it displays properly when called in awakeFromNib.
Related
EDIT: I have figured out the answer on my own but here it is for anyone else who needs it:
UIImageViews cannot be shared so a different instantiation of each UIImageView is required for each visible cell. Now you know.
I have a custom table that has 2 types of cells. One cell is just set to toggle between a normal accessory of type checkmark. Another cell is set to have a custom image as the accessory type. When selected that accessory image changes to its opposite type, showing an "Invited" or "Invite" message.
I've narrowed down the code at fault to the following, found within my tableView:cellForRowAtIndexPath delegate method.
if(indexPath.section == 0){
cell = [tableView dequeueReusableCellWithIdentifier:self.directCellID];
cellValue = [self.contactsUsingApp objectAtIndex:indexPath.row];
cell.imageView.image = [self getContactImage:indexPath.row];
//vvvvvvvvvvvvvvvvv This is the section at fault vvvvvvvvvvvvvvvvv
if([self.selectedContactsUsingApp containsObject:indexPath])
cell.accessoryView = self.invitedStatus;
else
cell.accessoryView = self.notInvitedStatus;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
If I comment out that section I no longer have runaway memory usage (the Simulator showed me that there was some sort of constant allocation going on, it got up passed 1.29Gb after starting from 40Mb) but, obviously, the images no longer show.
If it matters the UIImageViews are initialized as follows:
UIImage *invite = [self imageWithImage:[UIImage imageNamed: #"invite_btn.png"] scaledToSize:CGSizeMake(40, 20)];
UIImage *invited = [self imageWithImage:[UIImage imageNamed: #"invited_btn.png"] scaledToSize:CGSizeMake(40, 20)];
self.notInvitedStatus = [[UIImageView alloc]initWithImage:invite];
self.invitedStatus = [[UIImageView alloc]initWithImage:invited];
(imageWithImage:scale is a function that returns a resized image to the appropriate scale accounting for retina found here: The simplest way to resize an UIImage?)
The same freezing happens when I select one of the cells because my tableView:didSelectRowAtIndexPath method works by the same toggling logic as the initialization method.
Help?
I have figured out the answer on my own but here it is for anyone else who needs it: UIImageViews cannot be shared so a different instantiation of each UIImageView is required for each visible cell. Now you know.
I am trying to display an array of images in a UICollectionView. The cells are being displayed, but the images are not.
Here is the cell being built:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:identifier
forIndexPath:indexPath];
UIImageView * catagoryImage = [[UIImageView alloc] initWithFrame:CGRectMake((cell.frame.origin.x),(cell.frame.origin.y), cell.frame.size.width, cell.frame.size.height)];
[catagoryImage setImage:[UIImage imageNamed:[Apps objectAtIndex:indexPath.row]]];
[cell.layer setCornerRadius:4];
[cell addSubview:catagoryImage];
cell.clipsToBounds = NO;
return cell;
}
And here is the array being declared:
Apps = [NSArray arrayWithObjects:#"Appstore.jpg", #"2.gif", #"3.gif", #"4.gif", #"5.gif", #"7.gif", #"8.gif",#"9.gif", nil];
Any ideas?
You have a few options, but I'll name 2:
This. It's a bit hacky. but it works
Subclass UICollectionViewCell
There are two problems with the code. The first, bigger one, is the idea of creating an image view on every invocation of cellForItemAtIndexPath.
This method is called every time a cell is scrolled into view, and the cells are reused, so your cells will end up with piles and piles of UIImageViews on top of one another as the user scrolls around.
Problem two is the coordinate system of the imageView frame. It should be placed relative to the cell's bounds, not the cell's frame which is in the parent view's (collection view's) coordinate space, so...
// see if this cell has an image view already
UIImageView *categoryImageView = (UIImageView *)[cell viewWithTag:128];
if (!categoryImageView) {
// only create one if we don't have one
CGRect frame = cell.bounds; // this is zero based, relative to the cell
categoryImageView = [[UIImageView alloc] initWithFrame:frame];
categoryImageView.tag = 128; // so we can find it later
[cell addSubview:categoryImageView];
}
// add it conditionally, but configure it unconditionally
categoryImageView.image = [UIImage imageNamed:[Apps objectAtIndex:indexPath.row]]];
Another possible problem with the code is access to the Apps objectAtIndex:. Apparently Apps is an unconventionally named instance of an NSArray. This is only okay if your numberOfItemsInSection datasource method returns Apps.count, and if all elements in the array are names of images in your app bundle.
Sussed it.
The images were outside the keyboard scheme and were in the container package.
Problem:
I use the following code inside the method cellForRowAtIndexPath to set the size of the image for the cell, yet at runtime the image gets blown up to the maximum height and width that the table row will allow.
UIImage *_image = [imageDictionary objectForKey:#"image"]; // Get image data
[_image drawInRect:CGRectMake(0,0,50,50)]; // set size
[cell.imageView setImage: _image]; // assign image to cell
cell.imageView.frame = CGRectMake(cell.imageView.frame.origin.x,cell.imageView.frame.origin.y,50,50);
return cell;
Question: Is there a more robust method of controlling the size of the image in a UITableViewCell? The approach I'm taking comes from several other posts but for some reason its being ignored in my code.
Side-note: I'm using Xcode 5 and developing on an iOS 7 platform.
Use UITableViewCell contentView .
The content view of a UITableViewCell object is the default superview for content displayed by the cell. If you want to customize cells by simply adding additional views, you should add them to the content view so they will be positioned appropriately as the cell transitions into and out of editing mode.
Example:
UIImage *_image = [imageDictionary objectForKey:#"image"]; // Get image data
[_image drawInRect:CGRectMake(0,0,50,50)]; // set size
UIImageView *imageView = [[UIImageView alloc] initWithImage: _image];
[imageView setFrame:yourFrame];
[cell.contentView addSubview:imageView];
This doesn't answer the question but your underlying problem is your approach. You should be customizing your cells by subclassing UITableViewCell. To add to that it's a lot easier to manipulate cell contents as views than to play around with the default picture and text label they give you. To carify, the contents of the cell sit on a view known as contentView accessible as cell.contentView. You can add text labels, buttons, and images as subviews to any location with any size you want the same way you would do with any view added as a subview.
I'm creating a mail screen using which visually resembles the iOS native email app. It looks like this (Both images are of the same screen. First one is the top half and the second one is the rest of it).
The difference is my mail screen has more custom fields in addition to normal To, Cc, Subjet fields.
I'm using a UITableViewController to create this. Below is a code snippet which creates a cell (For each cell it's pretty much the same).
- (UITableViewCell *)tokenTableView:(TITokenTableViewController *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
self.tableView.frame = CGRectMake(0,0,320,320);
UIView *contentSubview = nil;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifierSubject];
if(!self.txtSubject) {
self.txtSubject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.txtSubject.frame = CGRectMake(10, cell.frame.size.height / 2 - self.txtSubject.font.lineHeight / 2, tableView.tableView.bounds.size.width, 30);
self.txtSubject.placeholder = #"Subject";
[self setupMailData:indexPath.row];
}
contentSubview = self.txtSubject;
}
Say, I open up a draft. All the details in the input fields are filled and without changing anything, I hit send and it crashes the app. I know what's causing this. The problem is that normally the cells that are under the viewable portion of the screen gets created as you scroll down, right? But in this scenario, if I send it without scrolling down but those cells below the viewport don't exist thus it throws the error.
If I open the draft, scroll down and hit send, it works fine.
I need to know if there's a way to create all these cells at once. Even the cells that are below the viewport at first. Not depending on the user to scroll down.
I hope you have an idea about my situation. Can anyone suggest a solution?
Thank you.
follow steps:
Take uiscrollview and set scrollview frame as which you want to display.
Take uitableview as a subview of uiscrollview
set property Scrolling Enabled = NO (uncheck checkbox in .xib) of uitableview
call reloaddata method of uitableview
set tableview frame and contentsize of scrollview
tblEmail.frame = CGRectMake(yourXPos, yourYPos, yourWidth, tblEmail.contentSize.height);
scrollObj.contentSize = CGSizeMake(yourScrollWidth,tblEmail.contentSize.height+10);
so, the height of tableview is equal its contentsize. so, its create all cells at a time. and set contentsize of scrollview is equal tableview contentsize. so, the scrolling feature is worked like uitableview scrolling...
Use a Storyboard, add a UITableViewController and set the 'Content' to StaticCells.
Then you can define all the cells and their content in the Storyboard. You can even wire stuff up to IBOutlets in your UITableViewController subclass and they will all be there for you when viewDidLoad is fired ...
When using a Storyboard your code for getting the ViewController looks like:
[[UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil] instantiateInitialViewController];
I have an error with my custom UITableViewCell image not showing up until the UITableView is scrolled. It dosnt happen to all of the cells only the next one comming on or the most recent one comming off (for instane if you see half of the cell on the bottom you cannot see the image until you scroll it all the way into view)
So I have decided that maybe I need to do a better job of relating my UIImages to the correct custom cell.
I have created a UIImageView called "firstImageView" I then go into my interface builder and relate that to the correct UIImageView.
Then inside tableview:cellForRowAtIndexPath: I try to set it like this
myCustomCell.firstImageView.image = [UIImage imageNamed:#"SMILE.png"];
However I get this error
Property 'firstImageView' not found on object of type 'UITableViewCell *'
Any help would be appreciated
To address your error with upcoming images, here is my answer: When you get your UITableViewCell like this
MyCustomCell *myCustomCell = [self.tableView dequeueReusableCellWithIdentifier:#"myCustomCellIdentifier"];
you can implement -(void)prepareForReuse method of your override of UITableViewCell. Otherwise it is also possible to set the custom content in your -(UITableViewCell *)tableView:cellForRowAtIndexPath: method after dequeuing your cell.
You can get further information here:
How to use prepareForUse-Method and Apple Documentation of UITableViewCell
To address the other problem with unknown class attribute: What type is your myCustomCell? In the interface builder you have to assign the correct type and your myCustomCell also has to be of the correct type.
here 122,111 are THE frames for image view in table view cell replace it with yours ``
UIGraphicsBeginImageContextWithOptions(itemSize, NO,UIScreen.mainScreen.scale); ˚˚CGSize itemSize = CGSizeMake(122,111);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[imageView.image drawInRect:imageRect];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
When dequeueing the cell are you casting it as your custom cell class?
MyCustomCellClass *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
It looks like you created a custom UITableViewCell subclass but you don't dequeue it using the Identifier you assigned in IB ("reuse identifier")..