I am setting an table cell ImageView from a URL like the following:
NSURL *url = [[NSURL alloc] initWithString:[account valueForKeyPath:#"Avatar"]];
[cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"default.png"]];
I am then using a table cell subclass and resizing the image and making it round like the following:
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.bounds = CGRectMake(0,0,32,32);
self.imageView.layer.cornerRadius = 16;
self.imageView.clipsToBounds = YES;
}
This works great until I actually tap on a table row. It will then shift the image to the left some pixels.
It's only the images that aren't a perfect square. Example 100x75 instead of 100x100
I must be missing something small here? Here is a small image showing the offset:
FYI I'm referencing this post: How do I make UITableViewCell's ImageView a fixed size even when the image is smaller
EDIT
I've also tried this as the table cell cellForRowAtIndexPath:
This seems to work, however, for some reason when the table view is loaded not all images are loaded in until I start scrolling
[[SDWebImageManager sharedManager] downloadImageWithURL:url options:0 progress: nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
// resize image code here, then set below
cell.imageView.image = image;
}];
In my case I did this
-(void)layoutSubviews
{
[super layoutSubviews];
[self layoutIfNeeded];
self.imageView.layer.cornerRadius = (self.imageView.bounds.size.width / 2.0);
self.imageView.layer.masksToBounds = YES;
}
I haven't change bounds at run time. Hope it helps
FYI I ended up just creating a custom UITableViewCell with a UIImageView defined width/height 32x32 and custom labels to essentially mimic the Right Detail view.
You can try adding cell.setNeedsLayout() after setting Cell's image view, if all images have same dimensions!
MenuController.shared.fetchImage(url: item.imageURL) { (image) in
if let image = image {
DispatchQueue.main.async {
cell.imageView?.image = image
cell.setNeedsLayout()
}
}
}
Try this:
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(0,self.frame.size.width/2-16,32,32);
self.imageView.layer.cornerRadius = 16;
self.imageView.clipsToBounds = YES;
}
Or you may try set autoresizingMask
Related
I am attaching a sample project to allow you to test and see what I can do to fix this.
I am trying to resize the height's image dynamically and at the same time round two corners on every other cell. Doing so results in a mask that is cut off.
Basically here is what I am trying to achieve:
UITableView's row height is set to automatic.
_nTableView.rowHeight = UITableViewAutomaticDimension;
_nTableView.estimatedRowHeight = 150;
Download images using SDWebImage library using a CustomTableViewCell
[self.nImageView sd_setImageWithURL:[NSURL URLWithString:imageUrl] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL){}];
Configure a cell to round the corners depending on its row
UIBezierPath *maskPath = [UIBezierPath
bezierPathWithRoundedRect:self.bubbleView.bounds
byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerTopLeft)
cornerRadii:CGSizeMake(20, 20)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bubbleView.bounds;
maskLayer.path = maskPath.CGPath;
self.bubbleView.layer.mask = maskLayer;
Doing the above results in a mask being cut off but the height is calculated correctly. See below:
Based on this stack overflow's question, we need to remove the mask if there is one. I have tried to set the mask to nil in awakeFromNib method but that has no affect.
self.nImageView.layer.mask = nil;
self.nImageView.layer.masksToBounds = NO;
I also tried following the answers from this question but it results in the app crashing.
Thank you in advance.
Here is one possible solution - may not be the best, may not do exactly what you need, but might get you on your way...
Instead of trying to manipulate the layers / masks from within your custom UITableViewCell class, use a UIView subclass as the image holder. The code of that class can handle the rounded corners and layer/mask size updating.
See example here: https://github.com/DonMag/dhImage
To set height of row based on it's content:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(/*check if content is text label*/)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell1"];
UILabel *lbl = (UILabel*)[ cell.contentView viewWithTag:1000];
lbl.text = message;
[cell layoutIfNeeded];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
if(size.height < 100) {
return 100;
}
else {
return size.height;
}
}
else { // content is image
return 200;
}
}
Configure a cell to round the corners:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.
.
.
[cell.contentView.layer setCornerRadius:10.0f];
return cell;
}
To Download images using SDWebImage library:
SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader];
[downloader downloadImageWithURL:addr
options:0
progress:
^(NSInteger receivedSize, NSInteger expectedSize) {
// progression tracking code
}
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
if (image && finished) {
// Pass the imageView to this block
// After completion display downloaded image in imageView
imageView.image = image;
}
}];
Hope it helps!!
I have placed an image in a UITableViewCell and for some reason, the image is a bit blurred...
This is what I'm using:
NSURL *urlForProfileImage = [NSURL URLWithString: [_currentTweet[#"user"] objectForKey:#"profile_image_url_https"]];
UIImage *thumbnail = [UIImage imageWithData: [NSData dataWithContentsOfURL:urlForProfileImage]];
cell.imageView.image = thumbnail;
Is there another way to provide the desired result but maintain the images quality?
Reason :
The default imageView size is 40x40 and so your image needs to be 80x80 pixels (retina display).
But the image that you are getting from the "pbs.twimg.com/profile_images/192098593/Apple_normal.png" is 48x48.
And so it is blurred.
Solution :
One option is that you add a custom imageView which is 24x24. (width : 24 & height : 24) Then your image will not show blurred.
Or, you can try modifying the height and width of the imageView by subclassing the class UITableViewCell and using its layoutSubviews method. The "trick" is to write layout code in this method, otherwise the code does not have any effect :
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.bounds = CGRectMake(0,0,24,24);
self.imageView.frame = CGRectMake(0,0,24,24);
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
CGRect tmpFrame = self.textLabel.frame;
tmpFrame.origin.x = 30;
self.textLabel.frame = tmpFrame;
tmpFrame = self.detailTextLabel.frame;
tmpFrame.origin.x = 30;
self.detailTextLabel.frame = tmpFrame;
}
I have made a UIViewController which conforms to the UITableViewDataSource and UITableViewDelegate protocol and has a UITableView as it's subview.
I have set the backgroundView property of the table to be a UIImageView in order to display an image as the background of the table.
In order to have custom spacings between the cells I made the row height larger than I wanted and customised the cell's contentView to be the size I wanted, making it look like there is extra space (Following this SO answer).
I wanted to add a blur to the cell so that the background was blurred and I did this through Brad Larson's GPUImage framework. This works fine however, since I want the background blur to update as it scrolls, the scroll becomes very laggy.
My code is:
//Gets called from the -scrollViewDidScroll:(UIScrollView *)scrollView method
- (void)updateViewBG
{
UIImage *superviewImage = [self snapshotOfSuperview:self.tableView];
UIImage* newBG = [self applyTint:self.tintColour image:[filter imageByFilteringImage:superviewImage]];
self.layer.contents = (id)newBG.CGImage;
self.layer.contentsScale = newBG.scale;
}
//Code to create an image from the area behind the 'blurred cell'
- (UIImage *)snapshotOfSuperview:(UIView *)superview
{
CGFloat scale = 0.5;
if (([UIScreen mainScreen].scale > 1 || self.contentMode == UIViewContentModeScaleAspectFill)) {
CGFloat blockSize = 12.0f/5;
scale = blockSize/MAX(blockSize * 2, floor(self.blurRadius));
}
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, -self.frame.origin.x, -self.frame.origin.y);
NSArray *hiddenViews = [self prepareSuperviewForSnapshot:superview];
[superview.layer renderInContext:context];
[self restoreSuperviewAfterSnapshot:hiddenViews];
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return snapshot;
}
-(UIImage*)applyTint:(UIColor*)colour image:(UIImage*)inImage{
UIImage *newImage;
if (colour) {
UIGraphicsBeginImageContext(inImage.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect area = CGRectMake(0, 0, inImage.size.width, inImage.size.height);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -area.size.height);
CGContextSaveGState(ctx);
CGContextClipToMask(ctx, area, inImage.CGImage);
[[colour colorWithAlphaComponent:0.8] set];
CGContextFillRect(ctx, area);
CGContextRestoreGState(ctx);
CGContextSetBlendMode(ctx, kCGBlendModeLighten);
CGContextDrawImage(ctx, area, inImage.CGImage);
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
} else {
newImage = inImage;
}
return newImage;
}
Now for the question:
Is there a better way to add the blur? Maybe so that the layer doesn't have to be rendered each movement? iOS7's control centre/notification centre seem to be able to do this without any lagging.
Maybe with the GPUImageUIElement class? If so, how do I use this?
Another way I looked at was to create the blur on the background image initially and then crop just the areas I needed to use out, however I couldn't get this to work, since the images may or may not be the same size as the screen so the scaling was a problem (Using CGImageCreateWithImageInRect() and the rect being the cell's position on the table).
I also found out that I have to add the blur to the tableview itself with the frame being that of the cell, and the cell having a clear colour.
Thanks in advance
EDIT
Upon request, here is the code for the image cropping I attempted before:
- (void)updateViewBG
{
//self.bgImg is the pre-blurred image, -getContentViewFromCellFrame: is a convenience method to get just the content area from the whole cell (since the contentarea is smaller than the cell)
UIImage* bg = [self cropImage:self.bgImg
toRect:[LATableBlur getContentViewFromCellFrame:[self.tableView rectForRowAtIndexPath:self.cellIndexPath]]];
bg = [self applyTint:self.tintColour image:bg];
self.layer.contents = (id)bg.CGImage;
self.layer.contentsScale = bg.scale;
}
- (UIImage*)cropImage:(UIImage*)image toRect:(CGRect)frame
{
CGSize imgSize = [image size];
double heightRatio = imgSize.height/self.tableView.frame.size.height;
double widthRatio = imgSize.width/self.tableView.frame.size.width;
UIImage* cropped = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,
CGRectMake(frame.origin.x*widthRatio,
frame.origin.y*heightRatio,
frame.size.width*widthRatio,
frame.size.height*heightRatio))];
return cropped;
}
I managed to solve it with a solution I, at first, didn't think it would work.
Generating several blurred images is certainly not the solution as it costs a lot.
I used only one blurred image and cached it.
So I subclassed UITableViewCell :
#interface BlurredCell : UITableViewCell
#end
I implemented two class methods to access the cached images (blurred and normal ones)
+(UIImage *)normalImage
{
static dispatch_once_t onceToken;
static UIImage *_normalImage;
dispatch_once(&onceToken, ^{
_normalImage = [UIImage imageNamed:#"bg.png"];
});
return _normalImage;
}
I used REFrostedViewController's category on UIImage to generate the blurred image
+(UIImage *)blurredImage
{
static dispatch_once_t onceToken;
static UIImage *_blurredImage;
dispatch_once(&onceToken, ^{
_blurredImage = [[UIImage imageNamed:#"bg.png"] re_applyBlurWithRadius:BlurredCellBlurRadius
tintColor:[UIColorcolorWithWhite:1.0f
alpha:0.4f]
saturationDeltaFactor:1.8f
maskImage:nil];
});
return _blurredImage;
}
In order to have the effect of blurred frames inside the cell but still see the non blurred image on the sides, I used to scroll views.
One with an image view with the normal image and the other one with an image view with the blurred image. I set the content size to be the size of the image and the contentOffset will be set through an interface.
So the table view ends up with each cell holding the whole background image but cropping it at certain offset and still showing the entire image
#implementation BlurredCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
[self.contentView addSubview:self.normalScrollView];
[self.contentView addSubview:self.blurredScrollView];
}
return self;
}
-(UIScrollView *)normalScrollView
{
if (!_normalScrollView) {
_normalScrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_normalScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_normalScrollView.scrollEnabled = NO;
UIImageView *imageView =[[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.image = [BlurredCell normalImage];
_normalScrollView.contentSize = imageView.frame.size;
[_normalScrollView addSubview:imageView];
}
return _normalScrollView;
}
-(UIScrollView *)blurredScrollView
{
if (!_blurredScrollView) {
_blurredScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(BlurredCellPadding, BlurredCellPadding,
self.bounds.size.width - 2.0f * BlurredCellPadding,
self.bounds.size.height - 2.0f * BlurredCellPadding)];
_blurredScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_blurredScrollView.scrollEnabled = NO;
_blurredScrollView.contentOffset = CGPointMake(BlurredCellPadding, BlurredCellPadding);
UIImageView *imageView =[[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.image = [BlurredCell blurredImage];
_blurredScrollView.contentSize = imageView.frame.size;
[_blurredScrollView addSubview:imageView];
}
return _blurredScrollView;
}
-(void)setBlurredContentOffset:(CGFloat)offset
{
self.normalScrollView.contentOffset = CGPointMake(self.normalScrollView.contentOffset.x, offset);
self.blurredScrollView.contentOffset = CGPointMake(self.blurredScrollView.contentOffset.x, offset + BlurredCellPadding);
}
#end
setBlurredContentOffset: should be called each time the table view's content offset changes.
So in the table view delegate's implementation (the view controller) we do it in those two methods :
// For the first rows
-(void)tableView:(UITableView *)tableView willDisplayCell:(BlurredCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell setBlurredContentOffset:cell.frame.origin.y];
}
// Each time the table view is scrolled
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
for (BlurredCell *cell in [self.tableView visibleCells]) {
[cell setBlurredContentOffset:cell.frame.origin.y - scrollView.contentOffset.y];
}
}
Here is a complete working demo
I have read quite a few of the UICollectionView posts about poor scrolling, but none seem to directly apply or they are still unanswered.
I'm using AFNetworking to asynchronously load the images (95px squared) onto each cell and then when the images are scrolled into view again, the image is restored from cache (as verified by the response code given as 0 instead of 200).
Here's what I've tried:
Commented out weakCell.photoView.image = image; so the images aren't draw on screen and the scrolling was smoother (still stuttered a little during the HTTP get)
Removed all of the AFNetworking code from the cellForRowAtIndexPath method and the scrolling was much smoother (even with the custom cell shadows, etc. still being drawn on screen)
When I draw only the cell view (with the shadows) on screen, scrolling is very smooth for 100 cells. As soon as I start drawing the images on screen, scrolling is very poor on my device and it's even noticeable on the simulator. Instagram has very smooth scrolling for hundreds of cells on their profile view, so I'm trying to get close to their performance.
Are there any ways that I can improve any of my code below in order to improve scrolling performance?
Here is my cell code:
#import "PhotoGalleryCell.h"
#implementation PhotoGalleryCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Setup the background color, shadow, and border
self.backgroundColor = [UIColor colorWithWhite:0.25f alpha:1.0f];
self.layer.borderColor = [UIColor blackColor].CGColor;
self.layer.borderWidth = 0.5f;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowRadius = 3.0f;
self.layer.shadowOffset = CGSizeMake(0.0f, 2.0f);
self.layer.shadowOpacity = 0.5f;
// Make sure we rasterize for retina
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
self.layer.shouldRasterize = YES;
// Add to the content view
self.photoView = [[UIImageView alloc] initWithFrame:self.bounds];
[self.contentView addSubview:self.photoView];
}
return self;
}
- (void)prepareForReuse
{
[super prepareForReuse];
self.photoView.image = nil;
self.largeImageURL = nil;
}
And here is my UICollectionView code:
#pragma mark - Collection View Delegates
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [zePhotos count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotoGalleryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kPGPhotoCellIdentifier forIndexPath:indexPath];
// Get a reference to the image dictionary
NSDictionary *photoDict = [[zePhotos objectAtIndex:indexPath.row] objectForKey:#"image"];
// Asynchronously set the thumbnail view
__weak PhotoGalleryCell *weakCell = cell;
NSString *thumbnailURL = [[photoDict objectForKey:#"thumbnail"] objectForKey:#"url"];
NSURLRequest *photoRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:thumbnailURL]];
[cell.photoView setImageWithURLRequest:photoRequest
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
weakCell.photoView.image = image;
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Error retrieving thumbnail... %#", [error localizedDescription]);
}];
// Cache the large image URL in case they tap on this cell later
cell.largeImageURL = [[photoDict objectForKey:#"large"] objectForKey:#"url"];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"showPhotoDetail" sender:self];
}
You could try adding a shadowPath to your cell init, it should improve performance, that's the code I used on one of my project to add a rounded shadowPath (see the UIBezierPath methods for more choice)
self.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.frame.bounds
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(10, 10)].CGPath;
Moreover if I remember correctly AFNetworking doesn't resize the image returned from the server, so it could have an impact on the quality of your image (despite the scale method you added to the UIImageView), I recommend dispatching the returned image to resize it if you want as so :
CGSize targetSize = cell.photoView.bounds.size;
[cell.photoView setImageWithURLRequest:photoRequest
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
CGFloat imageHeight = image.size.height;
CGFloat imageWidth = image.size.width;
CGSize newSize = weakCell.imageView.bounds.size;
CGFloat scaleFactor = targetSize.width / imageWidth;
newSize.height = imageHeight * scaleFactor;
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *small = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(),^{
weakCell.photoView.image = small;
});
});
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Error retrieving thumbnail... %#", [error localizedDescription]);
}];
Code inspection looks good, though I bet it is the compositing of the shadow which is adding a good deal to the lag. The way you figure out exactly what is causing the delay is to use the Time Profiler tool in Instruments. Here are the docs from Apple.
The problem is when you scroll quickly you're starting up hundreds of network requests at the same time. If you have the image cached, display it immediately. If you don't, only start the download when the table view slows down.
You can use something like this:
//Properties or Instance Variables
NSDate *scrollDateBuffer;
CGPoint scrollOffsetBuffer;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSTimeInterval secondsSinceLastScroll = [[NSDate date] timeIntervalSinceDate:scrollDateBuffer];
CGFloat distanceSinceLastScroll = fabsf(scrollView.contentOffset.y - scrollOffsetBuffer.y);
BOOL slow = (secondsSinceLastScroll > 0 && secondsSinceLastScroll < 0.02);
BOOL small = (distanceSinceLastScroll > 0 && distanceSinceLastScroll < 1);
if (slow && small) {
[self loadImagesForOnscreenRows];
}
scrollDateBuffer = [NSDate date];
scrollOffsetBuffer = scrollView.contentOffset;
}
You will want to call loadImagesForOnscreenRows in other methods, like when new data comes in, viewWillAppear, and scrollViewDidScrollToTop.
Here's an example implementation of loadImagesForOnscreenRows:
- (void)loadImagesForOnscreenRows
{
#try {
for (UITableViewCell *cell in self.tableView.visibleCells) {
// load your images
NSURLRequest *photoRequest = …;
if (photoRequest) {
[cell.photoView setImageWithURLRequest:…];
}
}
}
#catch (NSException *exception) {
NSLog(#"Exception when loading table cells: %#", exception);
}
}
I have this in a try/catch block because in my experience [UITableView -visibleCells] isn't reliable - it occasionally returns deallocated cells or cells without a superview. If you make sure this method is only called when the table is not scrolling quickly, it shouldn't impact scroll performance too much.
Also, note that the AFNetworking UIImageView category doesn't expose the cache object. You'll need to modify it slightly to check if you already have an image cached; this answer should point you in the right direction.
I am very new to objective c and I'm just getting my bearings. I want to do something really simple but it proves to be quite a challenge:
I am trying to display an image into an UIImageView. The image I'm showing is large and I want it scaled down to fit the UIImageView. I tried setting the AspectFit View mode but the image gets displayed to the original size and is clipped by the UIImageView. My code is below:
- (void)changeImages
{
UIImage* img11 = nil;
img11 = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:#"dog" ofType:#"jpeg"]];
u11.contentMode = UIViewContentModeScaleAspectFit;
u11.image = img11;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self changeImages];
}
Can anyone shed some light on this please?
Thanks!
Hi I would try this...
- (void)changeImages
{
UIImage *img11 = [UIImage imageNamed#"dog.jpeg"];
u11.contentMode = UIViewContentModeScaleAspectFit;
u11.clipsToBounds = YES;
[u11 setImage:img11];
}
- (void)viewWillAppear:animated
{
[super viewWillAppear:animated];
[self changeImages];
}
This will scale the image (up or down) so that it fits inside the imageView. Having clipsToBounds isn't necessary but will stop the image from displaying outside the frame of your imageView.
HTH.
Add to your UIViewController.m:
-(UIImage *)resizeImage:(UIImage *)image imageSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0,0,size.width,size.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// here is the scaled image which has been changed to the size specified
UIGraphicsEndImageContext();
return newImage;
}
Using:
UIImage *image = [UIImage imageNamed:#"image.png"];
CGSize size = CGSizeMake(50, 63); // set the width and height
UIImage *resizedImage = [self resizeImage:image imageSize:size];
I hope it helps.
CGSize size=CGSizeMake(79, 84);//set the width and height
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0,0,size.width,size.height)];
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//here is the scaled image which has been changed to the size specified
UIGraphicsEndImageContext();
This works for sure and don't forget to import QuartzCore FrameWork..
Have a Happy Coding (^_^)....
You can also set View:Mode to Aspect Fit in the Attributes Inspector in Interface Builder
I did the following and it helped
change the mode to "aspect fill" from the default value "Scale to fill"
and add a line of code as follows (I did it in a cell configuration):
cell.photo.clipsToBounds = true
I know this is old but I wanted to add a response based on the Stanford 193p 2017 lecture 11 (around 18:45) and for anyone looking in swift as this is the first search result that showed up for me.
Basically, subclass UIView and make it look like:
class U11: UIView {
var myImage: UIImage? { didSet { setNeedsDisplay() }}
override func draw(_ rect: CGRect) {
myImage?.draw(in: bounds)
}
}
Then set the image with:
func changeImage() {
if let img11 = UIImage(named: "dog.jpeg"){
u11.myImage = img11
}
}
This is super simple and the image takes up the whole space inside of the views bounds.