cell.imageView.image and indentationLevel on iOS 7 - objective-c

How to make a distance between the image and the text closer?
In ios 6 the same code displays normally, but in the new version of the distance increased.
I do everything by standard methods
[cell.textLabel setText: .....
// cell.indentationLevel = 0; // this is for test
UIImage * img = [UIImage imageNamed: # "image10.png"];
             NSData * imageData = UIImagePNGRepresentation (img);
            cell.imageView.image = [UIImage imageWithData: imageData];
attached image
https://www.dropbox.com/s/lt119xgozvzzstd/image01.png

If I remember correctly, the indentation level only affects the text. So when you're changing the indentation level/width you are in fact changing the distance between the imageView and the textLabel.
I tested this an unfortunately you can't make the indentationWidth negative. Thus you will need to subclass the UITableViewCell and set it up with your own views (I would suggest doing that in the Storyboard, with autolayout and make the indentation into a NSLayoutConstraint so that you have a property on your cell indentationConstant, for example which you can change). I have done this for a slightly different purposes, I needed to indent the whole contentView. No way around subclassing and creating custom views in Storyboard, sorry. (I am not even going to suggest some terrible hacks of accessing the subviews and modifying their frame, everything is autolayout today).

Related

Code to make screenshot of an entire UITableView doesn't work anymore in iOS 13

I used the code below for years to be able to capture a screenshot of an UITableView (including hidden rows) and save it to the user's phone gallery or share it.
Since they updated to iOS 13 it doesn't work anymore, it captures only the visible part of the table leaving it blank on the bottom part.
-(UIImage *)imageFromCurrentTable
{
CGRect frame = self.tableView.frame;
frame.size.height = self.tableView.contentSize.height;
self.tableView.frame = frame;
UIGraphicsBeginImageContext(self.tableView.bounds.size);
[self.tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
return [UIImage imageWithData:data];
}
What changed in iOS 13? How this code can be updated? (the code is Obj-C but I will accept also swift answers!)
I have faced this issue. Due to cell Reuse, UIGraphicsGetImageFromCurrentImageContext cannot produce full UITableView structure.
One Way [Not Efficient Way]:
In cellForRowAtIndexPath, we can able to get which UITableViewCell using. Store that cell in [Int: UITableViewCell].
Get screenshot from UITableViewCell.contentView.
Add that screenshot's image as subview to UIView one by one.
Now, UIView having UITableView's contentView as Images.
Get screenshot from UIView.

How do I programmatically change an image in an existing UIImageView and make it fit inside the image view's constraints?

I have a UIImageView and when I set an image in that view using IB, the image is the correct size when I run the app (40x40). When I programmatically change the image using the code below, the new image is 400x400 or so. This is using the same image that I know works fine if it's set in IB. Do I have to scale the image before I add it to the UIImageView? I assumed auto-layout's constraints would automatically do this for me.
UIImage *messageTypeImage = [UIImage imageNamed:message.imageName];
[messageCell.imageView setImage:messageTypeImage];
[messageCell.contentView layoutIfNeeded];
The UIImageView's content mode is set to "Scale To Fill" and I've tried adding the code below both before and after calling setImage:
[messageCell.imageView setContentMode:UIViewContentModeScaleAspectFill];
[messageCell.imageView setClipsToBounds:YES];
Here's how the constraints are set up for the image view:
Are you using iOS 8 SDK? If so, try overriding layoutSubviews in your cell subclass and add this:
self.contentView.frame = self.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
There are some problems with the contentViews' of collection view/table view cells constraints/masks.
Wow. Finally found the answer here. Turns out, there's a default imageView outlet in prototype cells. I was unknowingly using that outlet and not the UIImageView I thought I was using.

ios: Screenshot doesn't display mask Layer

I have a view with a certain background color. I am masking this view with the following code:
UIView *colorableView = [[UIView* alloc] init];
colorableView.backgroundColor = someColor;
CALayer *maskLayer = [CALayer layer];
maskLayer.contents = (id)[UIImage imageNamed:maskImageName].CGImage;
colorableView.layer.mask = maskLayer;
Ok everything works fine there. The view gets masked, so some parts are transparent. Now I make a screenshot of this view:
CGRect frame = colorableView.frame;
UIGraphicsBeginImageContext(frame.size);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(someUninterestingCodeToGetACorrectPosition);
[self.view.layer renderInContext:c];
UIImage *screenShotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenShotImage;
Taking a screenshot works (actually I display some other stuff above the view too and that gets displayed in the screenshot as well), but somehow, the mask is not recognized. Meaning what I get is a screenshot of a fully colored view (a rectangle) without the mask hiding some parts of it.
I guess ´UIGraphicsGetImageFromCurrentImageContext()`doesn't work with mask layers, so what can I do about it? I need to have a UIImage to display the screenshot in a mail.
Thanks a lot in advance
One way to fix this can be to use Quartz functions to clip the view (CGContextClip, I don't remember exactly, you'll have to dig a little bit into the documentation).
Hope this will help

How to refresh view in objective-c

I wanted to create a gallery. It loads different images based on the category, that a user selects. I used to populate images in UIImageViews.
My when selecting different categories is that it does not clear the previously selected images. This is my code for populating images.
-(void)refresh{
categoryLabel.text = treatment.treatmentName;
NSMutableArray *galleryImages =[NSMutableArray alloc] ;
galleryImages = [[PatientImage alloc]find:treatment.treatmentId];
int imgCount = [galleryImages count];
for(int i=0;i<imgCount;i++){
PatientImage *apatientImage = [galleryImages objectAtIndex:i];
UIImage *img1 = [UIImage imageNamed:apatientImage.imageBefore];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:img1];
myImageView.contentMode = UIViewContentModeTopRight;
myImageView.frame = CGRectMake(120+i*240,120.0,100.0, 100.0);
[self.view addSubview:myImageView];
UIImage *img2 = [UIImage imageNamed:apatientImage.imageAfter];
UIImageView *myImageView2 = [[UIImageView alloc] initWithImage:img2];
myImageView2.contentMode = UIViewContentModeTopRight;
myImageView2.frame = CGRectMake(120+i*240+300,120.0,100.0, 100.0);
[self.view addSubview:myImageView2];
}
}
First things first, You have some memory leaks there. You are allocating UIImageViews but are not releasing them anywhere, after you have added them to your view. I don't know if that applies to ARC, though. Same applies to your Mutable array, but I suppose you are releasing it after the 'for' loop somewhere, since it seems you posted code after omitting some of it.
As far as your actual question is concerned, I wouldn't do this this way. I would make the mutable array an object variable, and then fill it with my image views. When calling refresh again, I would first call -removeFromSuperview on each image view, then empty the array, then repopulate it and add the new subviews to my view. That is the simple way.
I don't know if you are using ARC, but you should be careful about memory management when using dynamically loaded views. Each time you add a view to another one, you increase its retain counter. You must then call release to remove ownership, and let the iOS runtime handle the rest.
Also note that operations such as this using views are expensive in terms of memory. So, another way of repopulating the gallery view is to just change the image an imageView holds. That will save you some memory, and time. In case the view doesn't have a constant number of images to be displayed, you can refine your algorithm to change the images on the already created image views, and then add more image views if necessary or delete the remaining ones, if any.
I hope I helped.
try at the start of refresh call
[[self subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
or
for (id imageView in self.subviews){
if([imageView isKindOfClass:[UIImageView class]]) [imageView removeFromSuperview];
}
call [tableview reloadData] if You are using tableview to show your gallery images
or call view's
[self.view setNeedsDisplay] method for refreshing the view.

Blending a UITableViewCell with a background

I have a dilemma I can't seem to solve. I have a UITableView populated by custom UITableViewCells and I need the background of each cell to be blended (like Photoshop multiply) with the background image (the background image is part of the UIView behind the UITableView).
I've found several ways to do the blend (and it does somewhat work). The blending function I'm using is:
- (UIImage *)blendOverlay:(UIImage *)topImage withBaseImage:(UIImage *)baseImage toSize:(CGFloat)imageSize
{
UIGraphicsBeginImageContext(CGSizeMake(imageSize, imageSize));
[baseImage drawInRect:CGRectMake(0.0, 0.0, imageSize, imageSize)];
[topImage drawInRect:CGRectMake(0.0, 0.0, imageSize, imageSize) blendMode:kCGBlendModeMulitply alpha:0.5];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
which is from http://www.cocoabuilder.com/archive/cocoa/280142-uiimageview-display-as-multiply.html.
Basically what I do now is chop out the piece of the background I'm over by getting the cell's frame and creating a new image which is the piece of the background in that frame. However, in order for the effect to work, it essentially needs to recalculate and update every frame (much like an alpha effect). Oh, and I tried just setting a timer to 1/60 seconds and calling
[tableView reloadData];
But that just slowed everything down and the redraws never actually occurred. Any help is much appreciated, I've been googling for nearly 3 hours to avail.
Oh, and for posterity purposes, I chop the background image like so:
CGRect r = [tableView rectForRowAtIndexPath:indexPath];
CGRect r2 = [tableView convertRect:r toView:self.view];
CGImageRef imageRef = CGImageCreateWithImageInRect([m_background.image CGImage], r2);
// Get the image by calling [UIImage imageWithCGImage:imageRef]
CGImageRelease(imageRef);
Thanks!
The problem is that a UITableView doesn't call the drawRect: method of the each individual UITabelViewCell while moving the rows. It seems to cache the view at the start of the table movement, and use that image for moving the whole table. Therefore the custom UITableViewCell has no opportunity to update the background image to show the movement of the blended backgrounds.
The one possible way I can see to animate the background image blending as the table cells move is to subclass UITableView and override drawRect: in that subclass.