After uploading image in content module how to update image?
i'm below code to upload file code
// Upload a file to the Content module
NSData *imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"image45" ofType:#"png"]];
[QBRequest TUploadFile:imageData fileName:#"arrow.png" contentType:#"image/png" isPublic:NO successBlock:^(QBResponse *response, QBCBlob *uploadedBlob) {
// set dialog's photo
NSUInteger uploadedFileID = uploadedBlob.ID;
dialog.photo = [NSString stringWithFormat:#"%d", uploadedFileID];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
// handle progress
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
Find This code for update content file
NSData *file = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"plus" ofType:#"png"]];
QBCBlob *blob = [QBCBlob blob];
blob.ID = 65268; // ID of exists file
blob.name = #"Plus";
[QBRequest TUpdateFileWithData:file file:blob successBlock:^(QBResponse *response) {
// File updated
// if blob.isPublic == YES
NSString *url = [blob publicUrl];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
// handle progress
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
Related
I am able to download file from GoogleDrive API.
Using the following code.
NSString *url = [NSString stringWithFormat:#"https://www.googleapis.com/drive/v3/files/%#?alt=media",
identifier];
GTMSessionFetcher *fetcher = [self.service.fetcherService fetcherWithURLString:url];
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
if (error == nil) {
NSLog(#"Retrieved file content");
// Do something with data
UIImage *img = [UIImage imageWithData:data];
NSLog(#"%#", img);
} else {
NSLog(#"An error occurred: %#", error);
[self showErrorAlert:error];
}
}];
It was working fine.(Getting image from data)
Now its not able to compose image.
UIImage *img = [UIImage imageWithData:data];
NSLog(#"%#", img);
Its giving Null.
Given a url like this:
file:///private/var/mobile/Applications/C133BAE7-0CBC-4E4F-826B-509B5E1EB68E/tmp/uzhMyDkL0mSI-SCVideo-Merged.mov
How can I get the NSData representation of this to send to a server? I've tried all of these:
NSData *videoData = [NSData dataWithContentsOfURL:url];
NSData *videoData = [NSData dataWithContentsOfFile:[url absoluteString]];
NSData *videoData = [[NSFileManager defaultManager] contentsAtPath:[url path]];
videoData is nil every time.
EDIT:
For more context I am trying to use SCRecorder to capture video.
- (void)recorder:(SCRecorder *__nonnull)recorder didCompleteSegment:(SCRecordSessionSegment *__nullable)segment inSession:(SCRecordSession *__nonnull)session error:(NSError *__nullable)error {
[session mergeSegmentsUsingPreset:AVAssetExportPresetHighestQuality completionHandler:^(NSURL *url, NSError *error) {
if (error == nil) {
//NSData *videoData = [NSData dataWithContentsOfURL:url];
//NSData *videoData = [NSData dataWithContentsOfFile:[url absoluteString]];
NSData *videoData = [[NSFileManager defaultManager] contentsAtPath:[url path]];
} else {
NSLog(#"Bad things happened: %#", error);
}
}];
}
The file URL looks correct to me but to be really sure, you should add in this method before trying to fetch NSData:
NSError *error = nil;
if ([url checkResourceIsReachableAndReturnError: &error] == FALSE)
{
NSLog(#"URL %# is not available because %#", [url absoluteString], [error localizedDescription]);
}
You can also try fetching the file via:
NSError *error = nil;
NSData *videoData = [NSData dataWithContentsOfURL:url
options: NSDataReadingUncached
error:&error];
if (videoData == nil)
{
NSLog(#"URL %# is not available because %#", [url absoluteString], [error localizedDescription]);
} else {
// you've likely got data, since videoData is not nil!
}
This is weird, but it works if I do this:
- (void)recorder:(SCRecorder *__nonnull)recorder didCompleteSegment:(SCRecordSessionSegment *__nullable)segment inSession:(SCRecordSession *__nonnull)session error:(NSError *__nullable)error {
[session mergeSegmentsUsingPreset:AVAssetExportPresetHighestQuality completionHandler:^(NSURL *url, NSError *error) {
if (error == nil) {
[self getDataFromUrl:url];
} else {
NSLog(#"Bad things happened: %#", error);
}
}];
}
- (void)getDataFromUrl:(NSURL *)url {
NSError *error = nil;
NSData *videoData = [NSData dataWithContentsOfURL:url
options:NSDataReadingUncached
error:&error];
if (videoData == nil)
{
NSLog(#"URL %# is not available because %#", [url absoluteString], [error localizedDescription]);
} else {
NSLog(#"GOT IT");
}
}
videoData is now valid NSData. Any explanation on why this works if separated into a different method?
Here is my code how to download image from URL and save it into document directory using AFNetworking.
Now, my question is if image is already downloaded from URL then image is loaded from cache instead of re-download it. I want to do this using AFNetworking. I know that the solution for this problem is inside #import "UIKit+AFNetworking/UIKit+AFNetworking.h"
If anyone have any idea of how to help, please help me solve my issue.
#import "ViewController.h"
#define URL #"https://upload.wikimedia.org/wikipedia/commons/e/ec/USA-NYC-American_Museum_of_Natural_History.JPG"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.progressBar.hidden = YES ;
self.lblProgressStatus.hidden = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)Action:(UIButton *)sender
{
self.progressBar.hidden = NO ;
self.lblProgressStatus.hidden = NO ;
self.ActionDownload.enabled = NO ;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *strURL = [NSURL URLWithString:URL];
NSURLRequest *request = [NSURLRequest requestWithURL:strURL];
NSProgress *progress;
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
}
completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
[self.progressBar setHidden:YES];
self.lblProgressStatus.text = #"Download completed" ;
NSLog(#"File downloaded to: %#", filePath);
NSString * strTemp = [NSString stringWithFormat:#"%#", filePath];
NSArray *components = [strTemp componentsSeparatedByString:#"/"];
id obj = [components lastObject];
NSLog(#"%#", obj);
NSString *docPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
NSString *strFilePath = [NSString stringWithFormat:#"%#/%#",docPath, obj];
BOOL fileExists=[[NSFileManager defaultManager] fileExistsAtPath:strFilePath];
if (!fileExists)
{
NSLog(#"File Not Found");
}
else
{
UIImage * image = [UIImage imageWithContentsOfFile:strFilePath];
self.imageView.image = image ;
}
[progress removeObserver:self forKeyPath:#"fractionCompleted" context:NULL];
}];
[self.progressBar setProgressWithDownloadProgressOfTask:downloadTask animated:YES];
[downloadTask resume];
[progress addObserver:self
forKeyPath:NSStringFromSelector(#selector(fractionCompleted)) options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"fractionCompleted"])
{
NSProgress *progress = (NSProgress *)object;
int temp = progress.fractionCompleted * 100 ;
// NSLog(#"%d", temp);
NSString * strTemp = #"%";
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
self.lblProgressStatus.text = [NSString stringWithFormat:#"%d %#", temp, strTemp];
});
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#end
You can download the image using this method defined in UIImageView+AFNetworking:
[imageView setImageWithURL:[NSURL URLWithString:URL] placeholderImage:[UIImage imageNamed:#"placeholder-avatar"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if ([[extension lowercaseString] isEqualToString:#"png"]) {
[UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"png"]] options:NSAtomicWrite error:nil];
} else if ([[extension lowercaseString] isEqualToString:#"jpg"] || [[extension lowercaseString] isEqualToString:#"jpeg"]) {
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", imageName, #"jpg"]] options:NSAtomicWrite error:nil];
}
} failure:NULL];
The success block will be called even if it gets the image from cache. Hope it helped!
It uses cache by default. To test, go to a url you have access to of an image, then delete the image, and load again, and you'll see it's cached :D The images sometimes are not cached if they're big images.
If you want to increase this cache size, put this in your app delegate:
[[NSURLCache sharedURLCache] setMemoryCapacity:(20*1024*1024)];
[[NSURLCache sharedURLCache] setDiskCapacity:(200*1024*1024)];
EDIT RE: comments:
If you're looking to only download images once to your documents path, then perhaps the best way to test if an image already exists and should be downloaded or not is a test you can create. E.g, if the last path component (the last part of an image file path) of an image exists already in your documents, don't download it, else download it.
EDIT: further comments
Inside UIKit+AFNetworking/UIImageView+AFNetworking.h
/**
Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled.
If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished.
By default, URL requests have a Accept header field value of "image / *", a cache policy of NSURLCacheStorageAllowed and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use setImageWithURLRequest:placeholderImage:success:failure:
#param url The URL used for the image request.
*/
- (void)setImageWithURL:(NSURL *)url;
This looks exactly like what you're looking for
to use:
#import <AFNetworking/UIKit+AFNetworking.h>
and use
NSURL *strURL = [NSURL URLWithString:#"http://www.example.com/image.jpg"];
[imageview setImageWithURL:strURL];
I recommend you to use this library https://github.com/rs/SDWebImage
So, you can do something like this:
- (void)loadImage:(NSURL *)url
{
__block UIImage *image = [[SDImageCache sharedImageCache] queryDiskCacheForKey:[url absoluteString]];
if(!image) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval: 30.0]; // Will timeout after 30 seconds
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data != nil && error == nil) {
image = [UIImage imageWithData:data];
NSData *pngData = UIImagePNGRepresentation(image);
[[SDImageCache sharedImageCache] storeImage:image imageData:pngData forKey:[url absoluteString] toDisk:YES];
}
else {
// There was an error, alert the user
NSLog(#"%s Error: %#", __func__, error);
}
}];
}
}
I'm trying to figure out how to get MWphotobrowser to fetch photo, photo caption, photo thumbnail etc. from a json file an extermal server.
In viewDidLoad, I have this code:
- (void)viewDidLoad {
NSURL *url = [NSURL URLWithString:#"https://s3.amazonaws.com/mobile-makers-lib/superheroes.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[super viewDidLoad];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
NSLog(#"Back from the web");
}];
NSLog(#"Just made the web call");
}
In Case3 MWphotobrowser's Menu.m, I have the following code:
case 3: {
photo.caption = [self.result valueForKeyPath:#"name"];
NSArray * photoURLs = [self.result valueForKeyPath:#"avatar_url"];
NSString * imageURL = [photoURLs objectAtIndex:indexPath.row];
[photos addObject:[MWPhoto photoWithURL:[NSURL URLWithString:imageURL]]];
enableGrid = NO;
break;
}
Incase you missed it, the JSON file I'm using is https://s3.amazonaws.com/mobile-makers-lib/superheroes.json
Nothing I tweak seems to make it work, any ideas how to fix this?
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
// here make sure ur response is getting or not
if ([data length] >0 && connectionError == nil)
{
// DO YOUR WORK HERE
self.superheroes = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &connectionError];
NSLog(#"data downloaded.==%#", self.superheroes);
}
else if ([data length] == 0 && connectionError == nil)
{
NSLog(#"Nothing was downloaded.");
}
else if (connectionError != nil){
NSLog(#"Error = %#", connectionError);
}
}];
in here u r getting the response from server is NSArray -->NSMutableDictionary` so
Case scenario is
case 3: {
NSDictionary *superhero = [self.superheroes objectAtIndex:indexPath.row];
photo.caption = superhero[#"name"];
NSString * imageURL = superhero[#"avatar_url"];
// NSArray * photoURLs = superhero[#"avatar_url"];
[photos addObject:[MWPhoto photoWithURL:[NSURL URLWithString:imageURL]]];
enableGrid = NO;
break;
}
ur final out put is
I have a loop set up that downloads a series a images which I will later use for to animate using the animationImages property of UIImageView. I would like to know when all the blocks inside my loops have finished executing so I could begin the animation, and was wondering how I may be able to tell when they are finished completing? Thanks!
for (PFObject *pictureObject in objects){
PFFile *imageFile = [pictureObject objectForKey:#"image"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:imageFile.url];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageFileURL];
[tokenImageView setImageWithURLRequest:imageRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[self.downloadedUIImages addObject:image]; //This is a mutableArray that will later be set to an UIImageView's animnationImages
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Error %#", error);
}];
}
//When I know all the blocks have finished downloading, I will then to animate the downloaded images.
Edit: having issue with Error -999
I am encountering the following issue when executing the code in the provided answer: Domain=NSURLErrorDomain Code=-999 "The operation couldn’t be completed. (NSURLErrorDomain error -999.)"
A quick search reveals that Error -999 means "another request is made before the previous request is completed" ... which is certainly the case here since I am making several requests in quick succession. The recommended fix suggested here didn't work for me as it will only successfully download one UIImage (the last one requested) , with the previous ones failing. I was wondering if there is workaround here or in AFNetworking that I ought to consider? Thanks!
Edit 2: working code based on #David's solution
for (PFObject *pictureObject in objects){
PFFile *imageFile = [pictureObject objectForKey:#"image"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:imageFile.url];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageFileURL];
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:imageRequest];
requestOperation.responseSerializer = [AFImageResponseSerializer serializer];
dispatch_group_enter(group);
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response: %#", responseObject);
UIImage *retrivedImage = (UIImage *)responseObject;
[self.downloadedUIImages addObject:retrivedImage];
dispatch_group_leave(group);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Image error: %#", error);
dispatch_group_leave(group);
}];
[requestOperation start];
counter ++;
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(#"Horray everything has completed");
NSLog(#"What is here %#", self.downloadedUIImages);
NSLog(#"Done");
});
Create a dispatch group, in the for loop enter the group, in the completion block leave the group. Then you can use dispatch_group_notify to find out when all blocks have completed:
dispatch_group_t group = dispatch_group_create();
for (PFObject *pictureObject in objects){
PFFile *imageFile = [pictureObject objectForKey:#"image"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:imageFile.url];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageFileURL];
dispatch_group_enter(group);
[tokenImageView setImageWithURLRequest:imageRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[self.downloadedUIImages addObject:image]; //This is a mutableArray that will later be set to an UIImageView's animnationImages
dispatch_group_leave(group);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Error %#", error);
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// do your completion stuff here
});
Count how many you've completed. The challenging part is making it thread safe. I recommend creating an atomic counter class for that.
Generic solution!
+ (void)runBlocksInParallel:(NSArray *)blocks completion:(CompletionBlock)completion {
AtomicCounter *completionCounter = [[AtomicCounter alloc] initWithValue:blocks.count];
for (AsyncBlock block in blocks) {
block(^{
if ([completionCounter decrementAndGet] == 0) {
if (completion) completion();
}
});
}
if (blocks.count == 0) {
if (completion) completion();
}
}
NSMutableArray *asyncBlocks = [NSMutableArray array];
for (PFObject *pictureObject in objects){
[asyncBlocks addObject:^(CompletionBlock completion) {
PFFile *imageFile = [pictureObject objectForKey:#"image"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:imageFile.url];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageFileURL];
[tokenImageView setImageWithURLRequest:imageRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[self.downloadedUIImages addObject:image]; //This is a mutableArray that will later be set to an UIImageView's animnationImages
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Error %#", error);
} completion:completion];
}];
}
[BlockRunner runBlocksInParallel:[asyncBlocks copy] completion:^{
//Do your final completion here!
}];
Set up a property and initialize it to the number of cycles - objects.count. In the completion of the block, lower the number down. When you reach zero, you are done.
for (PFObject *pictureObject in objects){
PFFile *imageFile = [pictureObject objectForKey:#"image"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:imageFile.url];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageFileURL];
[tokenImageView setImageWithURLRequest:imageRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[self.downloadedUIImages addObject:image]; //This is a mutableArray that will later be set to an UIImageView's animnationImages
if([[objects lastObject] isEqual:pictureObject]) {
[self animateImages];
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Error %#", error);
if([[objects lastObject] isEqual:pictureObject]) {
[self animateImages];
}
}];
}
- (void)animateImages {
//do animation here.
}