iOS 7 UITextView: Size of nstextattachment getting 2x after reopening the application - ios7

I am building a note editor using the Text Kit in ios7. Earlier I had trouble in rendering of custom size NSTextAttachment's as it was slowing down the rendering to a great extent.I solved the issue by scaling the images and then adding them to textview.You can find my answer in
iOS 7.0 UITextView gettings terribly slow after adding images to it
After scaling the images the textview rendering runs fine without any lag.The attributed text of textview is stored in core data.During a running session of application the textview displays the images correctly.Even after saving the attributed text in the core data and retrieving it again to display on textview,the images look fine.But after killing the app and again running the application.The images get enlarged to 2x size.while scaling the images I used the following function and used [[UIScreen bounds] scale] to maintain the image quality.
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContextWithOptions(newSize, NO, [UIScreen mainScreen].scale);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
If I scale the images to 1.0 the images doesn't expand but the image quality is very bad.
What I Think where the problem lies?
The problem lies in the layout manager.
What I have Tried
I have tried subclassing the NSLayoutManager and overriding the
- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin
What I see is the attachment size is doubling when running a new session of the application.If I try to check the size of attachment and resize it.The lag starts coming again.
I am stucked with this problem from a quite time.Any suggestions would be much appreciated.

Could the reason due to retina display? If it is retina, you might need to reduce the size by 50% before storing. How about trying this:-
//Original Size that you want to store
CGSize imageSize = CGSizeMake(320.0f, 320.0f);
//Make the image 50% of the size for retina
if ([[UIScreen mainScreen] respondsToSelector:#selector(displayLinkWithTarget:selector:)] &&([UIScreen mainScreen].scale == 2.0)) {
// Retina display
imageSize = CGSizeMake(160.0f, 160.0f);
}
UIImage * storeImage = [self imageWithImage:self.image scaledToSize:imageSize]
//TODO: Store this image locally or whatever you want to do.

#interface MMTextAttachment : NSTextAttachment
{
}
#end
#implementation MMTextAttachment
//I want my emoticon has the same size with line's height
- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(CGRect)lineFrag glyphPosition:(CGPoint)position characterIndex:(NSUInteger)charIndex NS_AVAILABLE_IOS(7_0)
{
return CGRectMake( 0 , 0 , lineFrag.size.height , lineFrag.size.height );
}
#end
I think you can try this.

Related

Usage of retina images and setting an UIImageView

It is the first time that I need to use images with the name formats of like: #2x and -568h#2x But I do not understand when the -568#2x is used. This should be for iPhone 5 and up but, the image is not used on my iPhone 5S when testing.
I tried very hard searching for this problem, but I cannot find it.
Problem:
Only the #2x image is used on all devices, and the -568#2x is ignored totally. So there is a gap above my image on screen while I have set the UIImageView in Storyboard to fill the whole screen. So in my understanding, with the setImage it would look first in the Project folder, and then to the Asset Catalog. But still it does not take the -568#2x image and always take the #2x image.
I have also set the auto layout right for the UIImageView so it would fit top, bottom, left, right.
Code/Screen:
So I have 2 images in my Project folder as you can see on the image:
Link to image
Here is the gap on top:
Link to image
And then in my code I use this code for setting the image on my Outlet:
[[self image] setImage:[UIImage imageNamed:#"firstLaunch"]];
So what could be the problem? Am I totally wrong how the Automatic image names thingy is working?
Thanks!
You could do something like this:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
self.view.layer.contents = (id)[UIImage imageNamed:#"firstLaunch#R4"].CGImage;
} else {
self.view.layer.contents = (id)[UIImage imageNamed:#"firstLaunch#2x"].CGImage;
}

How to correctly show #2x retina images

  I'm using Xcode 4.5.2, the app is targeting iOS 6.0.
In my application, I am having trouble with showing iPad Retina images. I know I have to use the #2x~ipad.png extension in order to get them to properly show and I do that. My images are named according so they are all named the same besides the extension for each device.
Here is how I named it.
However,
NSString *name=#"appearanceConnection.png";
//NSString *name=#"appearanceConnection"; //I did check this
//I did check the target
UIImage *image = [UIImage imageNamed:name];
NSLog(#"%f",image.size.width);
shows me the width of #1x image.
If i try to set proper image name manually:
if ([[UIScreen mainScreen] respondsToSelector:#selector(displayLinkWithTarget:selector:)] &&
([UIScreen mainScreen].scale == 2.0)) {
// Retina display
name=#"appearanceConnection#2x~ipad.png";
NSLog(#"retina");
}
else
{
name=#"appearanceConnection.png";
NSLog(#"non-retina");
}
UIImage *image = [UIImage imageNamed:name];
NSLog(#"%f",image.size.width);
proper #2x picked and then it scaled by 2.0 when I'm adding it to view.
I cleaned/rebuild my project many times, I reset IOS simulator settings, no result.
What am I doing wrong?
update:
non-retina
retina:
NSLog(#"%f", image.scale)
after imageNamed method gives me 1.0
UPDATE 2:
I'm trying to optimize my animation appearance, so I want to load one big image once and cut it by frames.
Firstly, I load big image (#2x or 1#x), then using cycle
for (int i = 0; i<numberOfFrames; i++)
{
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage,
CGRectMake(i*width, 0.0f, width, height));
UIImage *animationImage = [UIImage imageWithCGImage:imageRef];
if (isFlip)
{
[animationImages insertObject:animationImage atIndex:0];
}
else
{
[animationImages addObject:animationImage];
}
CGImageRelease(imageRef);
}
i cut this big image and create animation.
width and height are multiplied by 2 if it is retina display.
Maybe here is a caveat?
UIImage *animationImage = [UIImage imageWithCGImage:imageRef];
returns me image scaled twice?
however, if I scale (0.5,0.5) UIImageView which is initialized by this image it fits. Have any idea why scaled twice?
the retina and non retina images will have the same width and height when used as a UIImage or something similar, think of it as on retina displays the DPI of the image is doubled, and not the width or height.
this is to keep things transparent when coding for retina and non retina.

Problems scaling a UIImage to fit a UIButton

I have a set of buttons and different sized images. I want to scale each image in order that it fits the button in the correct aspect ratio. Once I've scaled the image, I set the button's image property to the scaled version.
UIImage *scaledImage = [image scaledForButton:pickerButton];
[pickerButton setImage:scaledImage forState:UIControlStateNormal];
my scaledForButton method is defined in a class extension for UIImage. It looks like this:
- (UIImage *)scaledForButton:(UIButton *)button
{
// Check which dimension (width or height) to pay respect to and
// calculate the scale factor
CGFloat imageRatio = self.size.width / self.size.height;
CGFloat buttonRatio = button.frame.size.width / button.frame.size.height;
CGFloat scaleFactor = (imageRatio > buttonRatio ? self.size.width/button.frame.size.width : self.size.height/button.frame.size.height);
// Create image using scale factor
UIImage *scaledimage = [UIImage imageWithCGImage:[self CGImage]
scale:scaleFactor
orientation:UIImageOrientationUp];
return scaledimage;
}
When I run this on an iPad2 it works fine and the images are scaled correctly. However if I run it on a retina display (both in the simulator and on a device) the image does not scale correctly and is squished into the button.
Any ideas why this would happen on retina only? I've been scratching my head for a couple of days but can't figure it out. They're both running the same iOS and I've checked the scale and ratio outputs, which are always the same, regardless of device. Many thanks.
Found the answer here: UIButton doesn't listen to content mode setting?
If you're setting the .contentMode, it seems you have to set the imageView property of the UIButton, not just the UIButton, then it worked properly.
The problem on iPad 3 was as Herman suggested - the CGImage was still a lot larger than the UIButton, so even though it was scaled down, it still had to be resized to fit the button.

Can you resize a UIImage on iOS whilst retaining scale? For thumbnail generation

My app deals with images taken from the camera. I want to be able to resize these images to thumbnail size so I can display them inside cells on table views.
Resizing "on the fly" seems rather slow, so I was planning to resize them at the point the user imports them into the app, and store both the full size and thumbnail on my business objects, using the thumbnail for things like table views
This is the code that I use for generating thumbnails :
#import "ImageUtils.h"
#implementation ImageUtils
+(UIImage*) generateThumbnailFromImage:(UIImage*)theImage
{
UIImage * thumbnail;
CGSize destinationSize = CGSizeMake(100,100);
UIGraphicsBeginImageContext(destinationSize);
[theImage drawInRect:CGRectMake(0,0,destinationSize.width, destinationSize.height)];
thumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return thumbnail;
}
#end
Whilst this appears to resize the image correctly, and greatly improves the responsiveness of my tables, the scaling of the images is off.
The above will create a UIImage of 100 * 100, how can I force it to use an AspectFit or AspectFill approach?
The UIImageView I have on my table cell is 100 * 100, so I need to resize the image to fit into that, without distorting it.
Any pointers would be great!
I realize this is an old thread, however if you stumble upon this, there is now a simpler method in iOS6. I lost a lot of time trying to use this solution until I found the following in Apple's documentation.
Use either:
+ (UIImage *)imageWithCGImage:(CGImageRef)imageRef
scale:(CGFloat)scale
orientation:(UIImageOrientation)orientation
or
+ (UIImage *)imageWithCIImage:(CIImage *)ciImage
scale:(CGFloat)scale
orientation:(UIImageOrientation)orientation
If you wanted to use this to make a thumbnail from a UIImage named "image", you can use one line of code:
UIImage *thumbnail = [UIImage imageWithCGImage:image.cgImage
scale:someScale
orientation:image.imageOrientation];
I've found that numbers greater than one shrink the image and numbers less than one expand it. It must use the scale as a denominator on the underlying size property.
Make sure you import the necessary frameworks!
Input:
imageSize // The image size, for example {1024,768}
maxThumbSize // The max thumbnail size, for example {100,100}
Pseudo code:
thumbAspectRatio = maxThumbSize.width / maxThumbSize.height
imageAspectRatio = imageSize.width / imageSize.height
if ( imageAspectRatio == thumbAspectRatio )
{
// The aspect ratio is equal
// Resize image to maxThumbSize
}
else if ( imageAspectRatio > thumbAspectRatio )
{
// The image is wider
// Thumbnail width: maxThumbSize.width
// Thumbnail height: maxThumbSize.height / imageAspectRatio
}
else if ( imageAspectRatio < thumbAspectRatio )
{
// The image is taller
// Thumbnail width: maxThumbSize.width * imageAspectRatio
// Thumbnail height: maxThumbSize.height
}

Downloading images from a web server for the retina display iOS

I am downloading images from a webserver for display in a table view in my iOS application using the following code:
NSURL *url = [NSURL URLWithString:[imageArray objectAtIndex:indexPath.row]];
UIImage *myImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
cell.imageView.image = myImage;
The image view is a 60x60 placeholder and 120x120 for the retina display. I am going to assume the user has an iPhone 4. However, if I size the image to 120x120 it does not correct the issue, it just becomes too big for the the imageview. If I size the image to 60x60, on the webserver that is, then the image fits fine but its a little fuzzy. Anyone know how to fix this issue?
Thanks!
Let's first agree that your UIImageView is 60x60 points, meaning 60x60 pixels for a standard display and 120x120 pixels for a retina display.
For a UIImageView at 60x60 points, the image should be 60x60 pixels at scale 1.0 for a standard display and 120x120 pixels at scale 2.0 for a retina display. This means that your UIImage should always have a size of 60x60 points, but should have a different scale depending on the display resolution.
When getting the image data from your server, you should first check the scale of the device's screen and then request the appropriate image size (in pixels), like so:
if ([UIScreen mainScreen].scale == 1.0) {
// Build URL for 60x60 pixels image
}
else {
// Build URL for 120x120 pixels image
}
Then you should put the image data in a UIImage of size 60x60 points, at the appropriate scale:
NSData *imageData = [NSData dataWithContentsOfURL:url];
CFDataRef cfdata = CFDataCreate(NULL, [imageData bytes], [imageData length]);
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData (cfdata);
CGImageRef imageRef = CGImageCreateWithJPEGDataProvider(imageDataProvider, NULL, true, kCGRenderingIntentDefault);
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef
scale:[UIScreen mainScreen].scale
orientation:UIImageOrientationUp];
CFRelease (imageRef);
CFRelease (imageDataProvider);
CFRelease(cfdata);
Hope this helps.
If your downloaded image have a size 2X from your UIImageView dimension size. It's look fine for retina display in iPhone4.
see also there: http://mobile.tutsplus.com/tutorials/iphone/preparing-your-iphone-app-for-higher-resolutions/
Images downloaded from the web are not formatted for Retina Display the same way images bundled with your app (using the "#2x" suffix) are.
You can get/set the scale of any UIView with the aptly named scale: and setScale: methods to help you better display content from the web if you know it's intended for Retina Display devices.
Well the answer is as simple as it can be:
I would recommend always downloading the double density images from the server (as users with non retina display are very few) and setting in the imageview.
What you didn't do correctly is you didn't set the imageView to automatically fit the content.
You can do this either in IB by selecting the ImageView and setting the contentMode (mode) to scale to Fill, or by code:
imageView.contentMode = UIViewContentModeScaleToFill;