converting NSData to UIImage - working with NSURLRequest - objective-c

I've been working with AFHTTPRequestOperationManager calling my service that return an image and my code looked like this:
NSString *baseURLString = #"http://get_image/";
#try {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:baseURLString
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *imageStr = responseObject[0];
if([imageStr isKindOfClass:[NSNull class]]==NO)
{
NSData *imageData = [NSData dataWithBase64EncodedString:imageStr];
UIImage *image = [UIImage imageWithData:imageData];
self.myImage = (image==nil)? [UIImage imageNamed:#"noPhoto"]: image;
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
self.myImage = [UIImage imageNamed:#"noPhoto"];
}];
}
#catch (NSException *exception) {
NSLog(#"exception %#", exception);
}
since AFHTTPRequestOperationManager is async and I need a sync call how can I complete this code to produce my image:
NSString *baseURLString = #"http://get_image/";
NSURLResponse *response;
NSError *error;
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:p_baseURLString] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30];
// Make synchronous request
NSData *imageRequest = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
???
UIImage *image = [UIImage imageWithData:imageData];
self.displayedApartment.exteriorImage = (image==nil)? [UIImage imageNamed:#"noPhoto"]: image;
This is what I've tried in place of ??? all resulted in image=nil
using the imageRequest data as is
converting the imageRequest to base64 with [[NSData alloc] initWithBase64EncodedData:imageRequest options:0];
converting it to string and back to NSData
NSData NSString *imageStr = [NSString stringWithUTF8String:[imageRequest bytes]];
NSData *imageData = [NSData dataWithBase64EncodedString:imageStr];

If I'm reading your code correctly, I think your variable names might be causing some trouble. Try replacing the following line:
NSData *imageRequest = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
with
NSData *imageData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
and then see what UIImage *image = [UIImage imageWithData:imageData]; gives you. Unless there has been an error in the request, I can't see a reason why image wouldn't be properly instantiated unless it didn't represent an image object.

Why not just display the image using the AFNetworking function setImageWithURL, it takes the URL of an image and sets the UIImageView to that image. Its a much simpler way of doing things if you only need to display it.
It looks something like this:
[imageView setImageWithURL:[NSURL URLWithString:p_baseURLString]];
In the header file you'll have something like this:
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
Its much faster as well.

Related

Unable to fetch data from nsurl

NSURL *url = [NSURL URLWithString:[self.imageArray objectAtIndex:indexPath.row]];
NSLog(#"My URL : %#",url);
NSData *data = [NSData dataWithContentsOfURL:url];
NSLog(#"New Data : %#",data);
UIImage *tmpImage = [[UIImage alloc] initWithData:data];
cell.imageView.image = tmpImage;
i think i got your problem, check this like my upload image in your project.
i also make a gif about how to add this setting in your project , just follow the step in my gif.

can't download image from web and how to check image from web

So I have this method to download an image from imgur.com as shown below:
- (void)getImageForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"i.imgur.com/%#.jpg",
[self.IDArray objectAtIndex:indexPath.row]]];
NSData * imageData = [[NSData alloc] initWithContentsOfURL:url];
self.imageTest = [UIImage imageWithData: imageData];
}
and then log the size of the data with this:
NSLog(#"%lx", (unsigned long)imageData.length);
but the size of the image in the log says
0
previously I use this asynchronous method:
- (void)getImageForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"i.imgur.com/%#.jpg",
[self.IDArray objectAtIndex:indexPath.row]]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
UIImage *imageMain = [UIImage imageWithData:data];
self.imageTest = [[UIImage alloc] init];
self.imageTest = [self imageWithImage:imageMain forRowAtIndexPath:indexPath];
}];
self.imageTest = [UIImage imageWithData: imageData];
}
but the log also says 0
yes the url exist. I have log it in another another method it is: i.imgur.com/EXtwoxT
What did I do wrong? how do I check that the image has been downloaded properly?

can't download image from web

So I have this method to download an image from imgur.com as shown below:
- (void)getImageForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"i.imgur.com/%#.jpg",
[self.IDArray objectAtIndex:indexPath.row]]];
NSData * imageData = [[NSData alloc] initWithContentsOfURL:url];
self.imageTest = [UIImage imageWithData: imageData];
}
and then log the size of the data with this:
NSLog(#"%lx", (unsigned long)imageData.length);
but the size of the image in the log says
0
previously I use this asynchronous method:
- (void)getImageForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"i.imgur.com/%#.jpg",
[self.IDArray objectAtIndex:indexPath.row]]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
UIImage *imageMain = [UIImage imageWithData:data];
self.imageTest = [[UIImage alloc] init];
self.imageTest = [self imageWithImage:imageMain forRowAtIndexPath:indexPath];
}];
self.imageTest = [UIImage imageWithData: imageData];
}
but the log also says 0
yes the url exist. I have log it in another another method it is: i.imgur.com/EXtwoxT you can see for yourself
What did I do wrong? how do I check that the image has been downloaded properly?
EDIT :
for those who says it's the URL you can see my actual log below. you can copy&paste the URL in your browser to see if it exist (it does)
- (void)getImageForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"i.imgur.com/%#.jpg",
[self.IDArray objectAtIndex:indexPath.row]]];
NSLog(#"i.imgur.com/%#.jpg", [self.IDArray objectAtIndex:indexPath.row]);
//Asynchronous handler
// NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
// [NSURLConnection sendAsynchronousRequest:urlRequest
// queue:[NSOperationQueue currentQueue]
// completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// UIImage *imageMain = [UIImage imageWithData:data];
// self.imageTest = [[UIImage alloc] init];
// self.imageTest = [self imageWithImage:imageMain forRowAtIndexPath:indexPath];
// NSLog(#"%lx", (unsigned long)imageData.length);
// }];
//Synchronous handler
NSData * imageData = [[NSData alloc] initWithContentsOfURL:url];
self.imageTest = [UIImage imageWithData: imageData];
NSLog(#"%lx", (unsigned long)imageData.length);
}
2015-01-06 07:44:26.564 Huckleberry[12733:361944] i.imgur.com/EXtwoxT.jpg
2015-01-06 07:44:26.600 Huckleberry[12733:361944] 0
First off, your code is missing a protocol for the URL -- NSURL can handle different protocols and doesn't just default to http. Prefix http:// to your URL and see if that gets you some data.
Secondly, that URL isn't actually the URL of the image -- I believe that URL will return the whole HTML imgur page, which is most likely not what you want (since you're trying to create a UIImage with the data).
Instead, try looking into the Imgur API (https://api.imgur.com) -- there's even a link on that page to an example Obj-C library (https://github.com/geoffmacd/ImgurSession)

GIFs don't animate when using NSThread

I'm writing an application in Objective C and Cocoa for Mac OS X that loads GIFs from an external source and displays them on screen. The user searches for a term, GIFs are downloaded and placed into NSImageViews, and then those views are displayed in a scroll view.
Earlier, the GIFs were animated as expected. I then tried to use an NSThread to do the loading of the GIFs and adding to the scroll view separate from the main thread. Here is the method that is called in the thread:
- (void)threading:(id)obj
{
NSURL *url = [NSURL URLWithString: #"URL HERE"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setURL:url];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSError *error;
NSURLResponse *response;
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] options:NSJSONReadingMutableLeaves error:nil];
NSArray *gifs = [data objectForKey:#"data"];
for (int i = 0; i < 1; i++) { // try to load 1 gif
NSString *currentGifURL = #"whatever";
NSImageView *imgView = [[NSImageView alloc] initWithFrame:CGRectMake(10, 1820-100*i, 150, 120)];
// I tried using these 2 lines, still didn't work
//[imgView setAnimates:YES]; [imgView setImageScaling:NSScaleNone];
NSURL *imageURL = [NSURL URLWithString:currentGifURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
NSImage *image = [[NSImage alloc] initWithData:imageData];
imgView.image = image;
[_scrollView.documentView addSubview:imgView];
}
[_progressIndicator stopAnimation:self];
}
I later call
[NSThread detachNewThreadSelector:#selector(threading:) toTarget:self withObject:nil];
To create the thread. The images appear on screen, but only the first frame is displayed—they're not animated. Literally replacing the thread initialization with the code from inside the thread renders the same view, except the GIFs are animated. Is there something about threads that would prevent the GIFs from animating?
Thanks!
NSImageView is not threadsafe. use - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
- (void)threading:(id)obj
{
NSURL *url = [NSURL URLWithString: #"URL HERE"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setURL:url];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSError *error;
NSURLResponse *response;
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] options:NSJSONReadingMutableLeaves error:nil];
NSArray *gifs = [data objectForKey:#"data"];
for (int i = 0; i < 1; i++) { // try to load 1 gif
NSString *currentGifURL = #"whatever";
// I tried using these 2 lines, still didn't work
//[imgView setAnimates:YES]; [imgView setImageScaling:NSScaleNone];
NSURL *imageURL = [NSURL URLWithString:currentGifURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
NSImage *image = [[NSImage alloc] initWithData:imageData];
[self performSelectorOnMainThread:#selector(LoadImageView:) withObject:image waitUntilDone:NO];
}
[_progressIndicator stopAnimation:self];
}
-(void)LoadImageView : (NSImage *)image
{
NSImageView *imgView = [[NSImageView alloc] initWithFrame:CGRectMake(10, 1820-100*i, 150, 120)];
imgView.image = image;
[_scrollView.documentView addSubview:imgView];
}

Getting Image from URL Objective C

I'm trying to get an image from an URL and it doesn't seem to be working for me. Can someone point me in the right direction?
Here is my code:
NSURL *url = [NSURL URLWithString:#"http://myurl/mypic.jpg"];
NSString *newIMAGE = [[NSString alloc] initWithContentsOfURL:url
encoding:NSUTF8StringEncoding error:nil];
cell.image = [UIImage imageNamed:newIMAGE];
When I debug the newIMAGE string is nil so something isn't working there.
What you want is to get the image data, then initialize a UIImage using that data:
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: #"http://myurl/mypic.jpg"]];
cell.image = [UIImage imageWithData: imageData];
[imageData release];
As requested, here's an asynchronous version:
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: #"http://myurl/mypic.jpg"]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
// WARNING: is the cell still using the same data by this point??
cell.image = [UIImage imageWithData: data];
});
[data release];
});
Ok there's a couple of things wrong here:
The conversion from URL (url) to NSString (newImage) is incorrect, what the code actually does there is try to load the contents of "http://myurl/mypic.jpg" into the NSString.
The -imageNamed method takes a string that is a path of a local file, not a URL as an argument.
You need to use an NSData object as an intermediary, like in this example:
http://blogs.oreilly.com/digitalmedia/2008/02/creating-an-uiimage-from-a-url.html
the accepted answer asynchronous version worked very slow in my code. an approach using NSOperation worked light years faster. the code provided by Joe Masilotti --> objective - C : Loading image from URL? (and pasted below):
-(void) someMethod {
// set placeholder image
UIImage* memberPhoto = [UIImage imageNamed:#"place_holder_image.png"];
// retrieve image for cell in using NSOperation
NSURL *url = [NSURL URLWithString:group.photo_link[indexPath.row]];
[self loadImage:url];
}
- (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
{
[self.memberPhotoImage setImage:image];
}
In Swift 3 and 4
let theURL = URL(string:"https://exampleURL.com")
let imagedData = NSData(contentsOf: theURL!)!
let theImage = UIImage(data: imagedData as Data)
cell.theImageView.image = theImage
This will be done in the main thread.
And to perform the same in asynchronous/background thread
DispatchQueue.main.async(){
let theURL = URL(string:"https://exampleURL.com")
let imagedData = NSData(contentsOf: theURL!)!
let theImage = UIImage(data: imagedData as Data)
}
cell.theImageView.image = theImage
Updating upon Jim dovey answer,[data release] is no longer required because in the updated apple guidelines. Memory management is done automatically by ARC (Automatic counting reference) ,
Here is the updated asynchronous call,
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: #"your_URL"]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
self.your_UIimage.image = [UIImage imageWithData: data];
});
});