How can we upload an image in iPhone in a faster manner - iphone

NSURL * imageURL = [NSURL URLWithString:imageurldata];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
image1 = [UIImage imageWithData:imageData];
[image1 retain];
I wrote above code for uploading the image in iPhone, and i m showing a new view in which i am showing this image but image takes time to appear till then the screen is blank. We are taking the image from url and storing it in an object. Is there any to show the image and view at the same time?

Try this async approach:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSLog(#"Screen %# - pauseBannerFileImage download starts", self.name);
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:newUrlForImage]]];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(#"!-Screen %#-!pauseBannerFileImage downloaded", self.name);
self.imageView.image = image;
});
});

how to handle tiling of images on the fly.
You will only need the TileImageView classes and use it(not UIImageView as it handles data downloading asynchronously) as follows....
TileImageView *tileImageView = [[TileImageView alloc]initWithFrame:<myFrameAsPerMyNeeds>];
[tileImageView setTag:<this is the identifier I use for recognizing the image>];
[myImageScrollView addSubView:tileImageView];
[tileImageView startImageDownloading:imageurldata];
[tileImageView release];
Thanks,

As far as my knowledge, it will take some time to download the data from server.there is one way for covering the time delay is show the UIActivityIndicatorView while downloading the image data

You may want to initialize the view before it is actually needed so the load may have already occurred by the time a user needs a view.

Related

Reload own created UITableViewCell

I got a custom UITableViewcell which should load an Image when use that code:
- (void)setImageWithURL:(NSURL *)URL
{
dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(taskQ, ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:URL]];
imageView.image = image;
NSLog(#"test");
});
}
It loads the Image very fast, so I get the response "test" very fast, but it needs to load IN the tableView. Also if I select the row it loads the Image.
How can I fix this issue?
Thanks
As long as setImageWithURL: is called as an effect of cellForRowAtIndexPath, then it should should show up as you expect... however, you need to call imageView.image = image; on the main thread. This goes for ALL UI related tasks. So you'll want:
- (void)setImageWithURL:(NSURL *)URL
{
dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(taskQ, ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:URL]];
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = image;
NSLog(#"test");
});
});
}
EDIT:
Using NSOperationQueue.
Create an operation queue as a member of your view controller.
m_operationQueue = [NSOperationQueue new];
m_operationQueue.maxConcurrentOperationCount = 1 // if you want to load images in order;
Make sure you cancel operations when the view unloads and when the table will refresh using
[m_operationQueue cancelAllOperations];
Do your thing in setImageWithURL
- (void)setImageWithURL:(NSURL *)URL
{
[m_operationQueue addOperationWithBlock:^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:URL]];
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = image;
NSLog(#"test");
});
}];
}
EDIT again:
Sorry, forgot that setImage was in your custom table cell. You can either:
1) make it a static object that you initialize in the +(void)initialize; method of your cell
2) make it a static object available via class method on your view controller
2) make a singleton instance that is available to your table cell
The design preference is up to you and depends what other practices you've been using if you want to be consistent.
You should call [tableView reloadData] when you finish downloading the image.
There is a similar question with an accepted answer, but also it has a suggestion to use SDWebImage. Take a look: How to get UITableViewCell images to update to downloaded images without having to scroll UITableView

objective - C : Loading image from URL?

Sorry for question title. I can not find a suitable title.
I have UITableView content images from url when i open the UITableView the View did not show until the images loaded and that takes along time.
I get the images from JSON by php.
I want to show the table and then images loading process.
This is code from my app:
NSDictionary *info = [json objectAtIndex:indexPath.row];
cell.lbl.text = [info objectForKey:#"title"];
NSString *imageUrl = [info objectForKey:#"image"];
cell.img.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]];
[cell.img.layer setBorderColor: [[UIColor blackColor] CGColor]];
[cell.img.layer setBorderWidth: 1.0];
return cell;
Sorry my english is weak.
Perform the web request on a separate thread, to not block the UI. Here is an example using NSOperation. Remember to only update the UI on the main thread, as shown with performSelectorOnMainThread:.
- (void)loadImage:(NSURL *)imageURL
{
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:#selector(requestRemoteImage:)
object:imageURL];
[queue addOperation:operation];
}
- (void)requestRemoteImage:(NSURL *)imageURL
{
NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
UIImage *image = [[UIImage alloc] initWithData:imageData];
[self performSelectorOnMainThread:#selector(placeImageInUI:) withObject:image waitUntilDone:YES];
}
- (void)placeImageInUI:(UIImage *)image
{
[_image setImage:image];
}
You have to use NSURLConnection and NSURLRequest. First create and show your empty table view (maybe with placeholder images, that are stored locally in the app). Then you start sending requests. These requests will run in the background and you (the delegate) will be notified when a request is completed. After that you can show the image to the user. Try not to load all the images at once if you have a lot of them. And don't load the ones that are invisible to the user, only load those if he scrolls down.
There is a UITableView lazy image loading example that Apple provided: https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
Hopefully it's what you were looking for
This is among very common thing we do in our application.
You simply can have store the URLs in a persistent store e.g array or db & can get the images using Operation queue to download faster. You can set the priorities, cancel operations at anytime etc. Also, the application respond time will be quicker.

loading images from disk in iPhone app is slow

In my iPhone app, I am using the iPhone's camera to take a photo and save it do disk (the application's documents folder). This is how i save it:
[UIImageJPEGRepresentation(photoTaken, 0.0) writeToFile:jpegPath atomically:YES];
Using the most compression, I figured reading the image from disk would be quick. But its not! I use the image as the background image for a button in one of my views. I load it like this:
[self.frontButton setBackgroundImage:[UIImage imageWithContentsOfFile:frontPath] forState:UIControlStateNormal];
When I navigate to the view with this button, it is slow and choppy. How do I fix this?
+imageWithContentsOfFile: is synchronous, so the UI on your main thread is being blocked by the image loading from disk operation and causing the choppiness. The solution is to use a method that loads the file asynchronously from disk. You could also do this in a background thread. This can be done easily by wrapping the +imageWithContentsOfFile: in dispatch_async(), then a nested dispatch_async() on the main queue that wraps -setBackgroundImage: since UIKit methods need to be run on the main thread. If you want the image to appear immediately after the view loads, you'll need to pre-cache the image from disk so it's in-memory immediately when the view appears.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
UIImage *image = [UIImage imageWithContentsOfFile:frontPath];
dispatch_async(dispatch_get_main_queue(), ^{
[self.frontButton setBackgroundImage:image forState:UIControlStateNormal];
});
});
As an aside, if the button image happens a gradient, consider using the following properties to ensure the image file loaded from disk is tiny:
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets
or (deprecated, only use if you need to support iOS 4.x):
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight
This is the faster way I know. You'll need to import #import <ImageIO/ImageIO.h>
I use this code to download and compress images during a scroll, inside a scrollview and you barely notice the delay.
CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)mutableData, NULL);
CFDictionaryRef options = (CFDictionaryRef)[[NSDictionary alloc] initWithObjectsAndKeys:(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform, (id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent, (id)[NSNumber numberWithDouble:200.0], (id)kCGImageSourceThumbnailMaxPixelSize, nil];
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
UIImage *image = [[UIImage alloc] initWithCGImage:thumbnail];
// Cache
NSString *fileName = #"fileName.jpg";
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:#"thumbnail"];
path = [path stringByAppendingPathComponent:fileName];
if ([UIImagePNGRepresentation(image) writeToFile:path atomically:YES]) {
// Success
}
I face a very similar issue where I had to load hundreds of images from the directory. My performance was quite slow if I used UIImage(contentsOfFile:) method. The below method increased my performance to 70 %.
class ImageThumbnailGenerator: ThumbnailGenerator {
private let url: URL
init(url: URL) {
self.url = url
}
func generate(size: CGSize) -> UIImage? {
guard let imageSource = CGImageSourceCreateWithURL(url as NSURL, nil) else {
return nil
}
let options: [NSString: Any] = [
kCGImageSourceThumbnailMaxPixelSize: Double(max(size.width, size.height) * UIScreen.main.scale),
kCGImageSourceCreateThumbnailFromImageIfAbsent: true
]
return CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as NSDictionary).flatMap { UIImage(cgImage: $0) }
}
}

How to know when UIimageView finished loading?

In my view controller, how can I know when a certain UIImageView has finished loading (large jpeg from documents directory)? I need to know so that I can then swap a placeholder low-res imageview with this hi-res imageview. Do I need to create a custom callback to know this? Any way is fine.
By the way, here is a snippet of code where I load the image:
NSString *fileName = [NSString stringWithFormat:#"hires_%i.jpg", currentPage];
NSString *filePath = [NSString stringWithFormat:#"%#/BookImage/%#", [self documentsDirectory], fileName];
hiResImageView.image = [[[UIImage alloc] initWithContentsOfFile:filePath] autorelease];
UIImageView isn't doing any loading at all. All the loading is being done by [[UIImage alloc] initWithContentsOfFile:filePath], and your thread is blocked while the file is loaded (so the load is already complete by the time that call finally returns).
What you want to do is something like this:
- (void)loadImage:(NSString *)filePath {
[self performSelectorInBackground:#selector(loadImageInBackground:) withObject:filePath];
}
- (void)loadImageInBackground:(NSString *)filePath {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
[self performSelectorOnMainThread:#selector(didLoadImageInBackground:) withObject:image waitUntilDone:YES];
[image release];
[pool release];
}
- (void)didLoadImageInBackground:(UIImage *)image {
self.imageView.image = image;
}
You would set up self.imageView to display the low-res image and then call loadImage: to load the high-res version.
Note that if you call this repeatedly before didLoadImageInBackground: gets called from earlier calls, you may cause the device to run out of memory. Or you might have the image from the first call take so much longer to load than image from the second call that didLoadImageInBackground: gets called for the second image before it gets called for the first. Fixing those issues is left as an exercise for the reader (or for another question).

image loading problem in iPhone ? - from webservice

imgBiteSpot.clipsToBounds=YES;
NSData *imageData = [[[NSData alloc]init]autorelease];
imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ObjBitSpot.StrImagePath]];
if(imageData==0)
{
imgBiteSpot.image=[UIImage imageNamed:#"img-not-found.gif"];
}
else {
UIImage *imgs = [[UIImage alloc] initWithData:imageData];
UIGraphicsBeginImageContext(CGSizeMake(88,88));
[imgs drawInRect:CGRectMake(0.0, 0.0, 88.0, 88.0)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imgBiteSpot.image=newImage;
[imgs release];
}
I have loaded an image to imgBiteSpot.
The image is loaded from the webservice. The problem is that it takes too much time (35 seconds to 1 minute).
If I remove image -> code / load, the reaction time is just 0.2 seconds.
What is the solution to reduce the time for the image loading process?
Thanks in advance for your kind help.
You're using NSData's method dataWithContentsOfURL:, which loads the data synchronously from the server, and thus blocks on the thread until the image is received.
What you should do instead is load a blank or "loading" image into your UIImage, then use NSURLConnection to download the image asynchronously and display it when it's done. See the NSURLConnection reference and the URL Loading System doc.
I've written RemoteImage class to load images over the network asynchronously. It also takes care of freeing the memory when necessary. See this post: http://www.dimzzy.com/blog/2009/11/remote-image-for-iphone/