I'm trying to preview a downloaded file to system and the program crashes when performing the method called previewController:previewItemAtIndex:. From what I assumed is that is releasing the previewcontroller before it is displayed, but this error does not occur when the file is already in the documents folder. It only happens when trying to open the file right after it has been downloaded.
Here is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSUInteger count = [listSessionsST count];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Signature *object = [listSessionsST objectAtIndex:row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *lblInComplete = (UILabel*)[cell viewWithTag:4];
UIImageView *imgCheck = (UIImageView*)[cell viewWithTag:3];
//Sets the File Name
self.File = [[[NSString stringWithFormat:#"%#_%#.%#",object.FileName,object.ModDate,object.Extension]
componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] componentsJoinedByString: #""];
//Shows the loading screen while the file is being downloaded
[DejalBezelActivityView activityViewForView:self.view withLabel:#"Downloading" width:0 LoadingType:#"Full"];
[DejalActivityView currentActivityView].showNetworkActivityIndicator = YES;
//Calls the method that will begin downloading the file
[self performSelector:#selector(startDownload:) withObject:object.Location afterDelay:0.2];
}
- (void)startDownload:(NSString *)strLocation{
NSString *filePath = [NSString stringWithFormat:#"%#/tmp/%#", NSHomeDirectory(),self.File];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (fileExists)
{
[DejalBezelActivityView removeViewAnimated:YES];
//QuickLook APIs directly to preview the document
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
[[self navigationController] pushViewController:previewController animated:YES];
[previewController release];
}
else
{
NSDictionary *dictionary = [Signature downloadFile:self.File Path:strLocation];
if ([dictionary valueForKey:#"Error"] == nil)
{
//If no error has occurred while downloading then preview the file.
//QuickLook APIs directly to preview the document
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
[[self navigationController] pushViewController:previewController animated:YES];
[previewController release];
[DejalBezelActivityView removeViewAnimated:YES];
}
else
{
//If an error occurred while downloading then display message to user.
[DejalBezelActivityView removeViewAnimated:YES];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#""
message:[dictionary valueForKey:#"Response"]
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
}
// Returns the number of items that the preview controller should preview
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)previewController{
return 1;
}
// returns the item that the preview controller should preview
- (id)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
NSString *path = [NSString stringWithFormat:#"%#/tmp/%#", NSHomeDirectory(),self.File];
return [NSURL fileURLWithPath:path];
}
The method that downloads the file and saves it to the tmp folder
---------------------------------------------------------------
+ (NSDictionary *)downloadFile:(NSString *)strFile Path:(NSString *)strPath{
float freeSpace = 0.0f;
NSError *error = nil;
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[NSString stringWithFormat:#"%#/tmp", NSHomeDirectory()]
error: &error];
if (dictionary)
{
NSNumber *fileSystemFreeSizeInBytes = [dictionary objectForKey: NSFileSystemFreeSize];
freeSpace = [fileSystemFreeSizeInBytes floatValue];
}
else
{
//Handle error
NSLog(#"Error;%#",error);
return [NSDictionary dictionaryWithObjectsAndKeys:#"An error has occurred while downloading the file.",#"Response",#"Y",#"Error", nil];
}
if (freeSpace > 0.0f)
{
NSDictionary *dict = nil;
BOOL blnHasErroroccurred = NO;
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *encoded = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)strPath,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]%",
kCFStringEncodingUTF8 );
NSString *strURL = [NSString stringWithFormat:#"%#/DataTransfer/DownloadFile?EMP_ID=%#&FilePath=%#",
appDelegate.ServerAddress,
appDelegate.UserId,
encoded];
[encoded release];
NSURL *url = [NSURL URLWithString:strURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLResponse* response = nil;
NSError* resultError = nil;
NSData* dataResult = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&resultError];
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
if ([httpResponse statusCode] == 200)
{
#try
{
if (dataResult.length < freeSpace)
{
//Get the tmp directory
NSFileManager *fileManager =[NSFileManager defaultManager];
NSString *fileName = [NSString stringWithFormat:#"%#/tmp/%#", NSHomeDirectory(),strFile];
//Write the data to using the tmp directory
BOOL filecreationSuccess = [fileManager createFileAtPath:fileName contents:dataResult attributes:nil];
if(filecreationSuccess == YES)
{
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"",#"Response",nil,#"Error", nil];
}
else
{
blnHasErroroccurred = YES;
}
}
}
#catch (NSException *exception)
{
blnHasErroroccurred = YES;
}
}
else
{
blnHasErroroccurred = YES;
}
if(blnHasErroroccurred == YES)
{
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"An error has occurred while downloading the file.", #"Response", #"Yes",#"Error",nil];
}
[dataResult release];
return dict;
}
else
{
return [NSDictionary dictionaryWithObjectsAndKeys:#"Not enough disk space to download file.",#"Response",#"Y",#"Error", nil];
}
}
Related
In this method:
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error = nil;
NSURL *videoURL = [self videoURLWithData:self.connectionData error:&error];
if (videoURL)
self.moviePlayer.contentURL = videoURL;
else if (self.elFields.count > 0)
[self startVideoInfoRequest];
else
[self finishWithError:error];
}
videoURL is returned as nil and hence, it is going to the error block. Youtube video id that I am using is "5Uls9v1nnss". What seems to be the issue?
the videoURLWithData method which is used to retrieve the videoURL is this :
- (NSURL *) videoURLWithData:(NSData *)data error:(NSError * __autoreleasing *)error
{
NSString *videoQuery = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSStringEncoding queryEncoding = NSUTF8StringEncoding;
NSDictionary *video = DictionaryWithQueryString(videoQuery, queryEncoding);
NSMutableArray *streamQueries = [[video[#"url_encoded_fmt_stream_map"] componentsSeparatedByString:#","] mutableCopy];
[streamQueries addObjectsFromArray:[video[#"adaptive_fmts"] componentsSeparatedByString:#","]];
NSMutableDictionary *streamURLs = [NSMutableDictionary new];
for (NSString *streamQuery in streamQueries)
{
NSDictionary *stream = DictionaryWithQueryString(streamQuery, queryEncoding);
NSString *type = stream[#"type"];
NSString *urlString = stream[#"url"];
if (urlString && [AVURLAsset isPlayableExtendedMIMEType:type])
{
NSURL *streamURL = [NSURL URLWithString:urlString];
NSString *signature = stream[#"sig"];
if (signature)
streamURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#&signature=%#", urlString, signature]];
if ([[DictionaryWithQueryString(streamURL.query, queryEncoding) allKeys] containsObject:#"signature"])
streamURLs[#([stream[#"itag"] integerValue])] = streamURL;
}
}
for (NSNumber *videoQuality in self.preferredVideoQualities)
{
NSURL *streamURL = streamURLs[videoQuality];
if (streamURL)
{
NSString *title = video[#"title"];
NSString *thumbnailSmall = video[#"thumbnail_url"];
NSString *thumbnailMedium = video[#"iurlsd"];
NSString *thumbnailLarge = video[#"iurlmaxres"];
NSMutableDictionary *userInfo = [NSMutableDictionary new];
if (title)
userInfo[XCDMetadataKeyTitle] = title;
if (thumbnailSmall)
userInfo[XCDMetadataKeySmallThumbnailURL] = [NSURL URLWithString:thumbnailSmall];
if (thumbnailMedium)
userInfo[XCDMetadataKeyMediumThumbnailURL] = [NSURL URLWithString:thumbnailMedium];
if (thumbnailLarge)
userInfo[XCDMetadataKeyLargeThumbnailURL] = [NSURL URLWithString:thumbnailLarge];
[[NSNotificationCenter defaultCenter] postNotificationName:XCDYouTubeVideoPlayerViewControllerDidReceiveMetadataNotification object:self userInfo:userInfo];
return streamURL;
}
}
if (error)
{
NSMutableDictionary *userInfo = [#{ NSURLErrorKey: self.connection.originalRequest.URL } mutableCopy];
NSString *reason = video[#"reason"];
if (reason)
{
reason = [reason stringByReplacingOccurrencesOfString:#"<br\\s*/?>" withString:#" " options:NSRegularExpressionSearch range:NSMakeRange(0, reason.length)];
NSRange range;
while ((range = [reason rangeOfString:#"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound)
reason = [reason stringByReplacingCharactersInRange:range withString:#""];
userInfo[NSLocalizedDescriptionKey] = reason;
}
NSInteger code = [video[#"errorcode"] integerValue];
*error = [NSError errorWithDomain:XCDYouTubeVideoErrorDomain code:code userInfo:userInfo];
}
return nil;
}
You should use the latest version (2.0.2 as of writing) of XCDYouTubeKit, the successor of XCDYouTubeVideoPlayerViewController. The video 5Uls9v1nnss should play fine.
I'm having a trouble dynamically adding UIButtons with background image as subviews to a UIScrollView. Its kind of a image gallery using UIButtons on a scrollView. I have used this method for couple of my apps, it works fine for me with the static contents.
But this time, Im loading images from a web service and saved to documents directory, then call the method to create the gallery. Logic is same with my other apps. But I cannot figure out what is the issue here.
I'll put here both the codes one is for retrieving data and other is the creating gallery.
Data retrieving from server
-(void)loadDataFromServer{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
arrCats = [[NSMutableArray alloc]init];
arrPromos = [[NSMutableArray alloc]init];
//[spinMenu startAnimating];
// load promo images from the server
for(int i=0;i<[arrPromos count];i++)
{
NSString *urlString = [Constants getImages:[[arrPromos objectAtIndex:i] objectForKey:#"image"]];
NSLog(#"Get Images API Call : %#", urlString);
NSURL *imageurl = [NSURL URLWithString:urlString];
//get a dispatch queue
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//this will start the image loading in bg
dispatch_async(concurrentQueue, ^{
NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageurl];
//this will set the image when loading is finished
dispatch_async(dispatch_get_main_queue(), ^{
if(imageData != nil){
// save the images temporally
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:[[arrPromos objectAtIndex:i] objectForKey:#"image"]]; //Add the file name
[imageData writeToFile:filePath atomically:YES];
}
});
});
}
// Load promotions from server
dispatch_async(queue, ^{
NSLog(#"Promotions Loading Started");
NSString *urlString = [Constants getAllPromotions:#"GetPromo.php"];
NSLog(#"Get Promotions API Call : %#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Specify that it will be a GET request
request.HTTPMethod = #"GET";
[request setHTTPShouldHandleCookies:NO];
NSURLResponse *responseURL;
NSError *error;
NSData *dataPromotions = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseURL error:&error];
if (responseURL == nil)
{
// Check for problems
if (error != nil)
{
NSLog(#"Get Promtions Connection failed! Error - %#", [error localizedDescription]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Connection Error!" message:#"Promotions data failed to load!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
else
{
NSString *responseString = nil;
responseString = [[NSString alloc] initWithData:dataPromotions encoding:NSUTF8StringEncoding];
if ([responseString rangeOfString:#"error"].location == NSNotFound)
{
NSDictionary *response = [[NSDictionary alloc] init];
response = (NSDictionary *)[responseString JSONValue];
NSLog(#"Response : Promotions %#", response);
if(response != Nil){
if([response count]>0){
arrPromos = [NSMutableArray arrayWithArray:[response objectForKey:#"Promos"]];
NSLog(#"ArrPromos # loading %#", arrPromos);
// create promos galley
[self createPromosGallery];
}
}
}
}
});
Note: [self createPromosGallery]; is calling after download all the images and data.
Create Gallery
-(void) createPromosGallery{
// sort arrPromos based on priority
for(int i=0; i<[arrPromos count];i++){
[arrPromos sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary *dict1 = obj1;
NSDictionary *dict2 = obj2;
NSString *string1;
NSString *string2;
if(![[dict1 objectForKey:#"priority"] isKindOfClass: [NSNull class]])
string1 = [dict1 objectForKey:#"priority"];
if(![[dict2 objectForKey:#"priority"] isKindOfClass: [NSNull class]])
string2 = [dict2 objectForKey:#"priority"];
return [string1 compare:string2 options:NSNumericSearch];
}];
}
NSLog(#"ArrPromos %#", arrPromos);
// scrollView size
CGFloat screenHieght = [UIScreen mainScreen].bounds.size.height;
if(screenHieght>500){
scrollView.frame = CGRectMake(0, 0, 320, 568);
}
else{
scrollView.frame = CGRectMake(0, 0, 320, 480);
}
// define scrollview height
int scrollHieght;
scrollHieght = ([arrPromos count]-1)/2;
NSLog(#"Scroll height %d",scrollHieght);
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width , scrollHieght * 160 +200);
scrollView.pagingEnabled = NO;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
scrollView.delegate = self;
for(int i=0;i<[arrPromos count];i++)
{
float x;
float y;
if(i%2==0)
{
x=30.0;
y=(i/2)*160+25;
}
if(i%2==1) {
x=170.0;
y=(i/2)*160+25;
}
// retreive saved images
NSString *strImgName;
UIImage *buttonUpImage;
// create buttons
button = [UIButton buttonWithType:UIButtonTypeCustom];
strImgName = [[arrPromos objectAtIndex:i] objectForKey:#"image"];
NSLog(#"Button image name %#", strImgName);
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#",docDirectory,strImgName];
buttonUpImage = [UIImage imageWithContentsOfFile:filePath];
[button setBackgroundImage:buttonUpImage forState:UIControlStateNormal];
button.frame = CGRectMake(x, y, 120,140);
[button setTag:i];
[button addTarget:self action:#selector(promoBtnPressed:)forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:button];
}
}
Note: I tested on both iOS 7 and 6. In iOS 7, it takes very long time to appear images on scrollView(Currently have only 2 images). Or else, If I TAP on scroolView then the images appear.
In ios 6, nothing appear
//Make a method that has url (fileName) Param
NSArray *documentsDirectory =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:url];
NSFileManager *fileManager =[NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:textPath])
{
return YES;
}
else
{
return NO;
}
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage
imageNamed:#""]];//Placeholder image
if ([url isKindOfClass:[NSString class]])
{
imgView.image = [UIImage imageNamed:[url absoluteString]];
imgView.contentMode = UIViewContentModeScaleAspectFit;
}
else if ([fileManager fileExistsAtPath:url])
{
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:url];
NSError *error = nil;
NSData *fileData = [NSData dataWithContentsOfFile:textPath options:NSDataReadingMappedIfSafe error:&error];
if (error != nil)
{
DLog(#"There was an error: %#", [error description]);
imgView.image=nil;
}
else
{
imgView.image= [UIImage imageWithData:fileData]
}
}
else
{ UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
CGPoint center = imgView.center;
// center.x = imgView.bounds.size.width / 2;
spinner.center = center;
[spinner startAnimating];
[imgView addSubview:spinner];
dispatch_queue_t downloadQueue = dispatch_queue_create("iamge downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
[spinner removeFromSuperview];
UIImage *image = [UIImage imageWithData:imgData];
NSError *error = nil;
[imgData writeToFile:url options:NSDataWritingFileProtectionNone error:&error];
if (error != nil)
}
else
{
}
imgView.image = image;
});
});
}
Thats UIImageView loading an image if it doesnot exist in document then it Save it , An Activity indicator is added to show image is loading to save,
Yes it is because you are downloading and then saving the images which takes time. I suggest you to use any library for downloading images and saving them.
Ex : SDWebImage
i want to save a video that i have downloaded before from URL.
I use this code where when i click on Download Button i will Download the video from the URL. I use the connection method and in the last i save video data using NSFileManager.
The problem is that i create a File path but inside it there aren't any type of data. How can i resolve it?
-(IBAction)download:(id)sender{
/*[downloadButton setEnabled:NO];
[webView setUserInteractionEnabled:NO];*/
//Prendo URL
NSString *getURL = #"";
getURL = [webView stringByEvaluatingJavaScriptFromString:#"function getURL() {var player = document.getElementById('player'); var video = player.getElementsByTagName('video')[0]; return video.getAttribute('src');} getURL();"];
//Prendo il titolo
videoTitle = videoTitleField.text;
NSArray *components = [videoTitle componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]];
videoTitle = [components componentsJoinedByString:#" "];
if ([getURL length] > 0) {
if ([videoTitle length] > 0) {
//videoTitle = [getTitle retain];
fileURL = [NSURL URLWithString:getURL];
downloadUrl = fileURL;
bytesReceived = percentComplete = 0;
localFilename = [[[fileURL absoluteString] lastPathComponent] copy];
receivedData = [[NSMutableData alloc] initWithLength:0];
app.networkActivityIndicatorVisible = YES;
//Inserisco alert view
alert = [[UIAlertView alloc] initWithTitle:#"Download" message:[NSString stringWithFormat:#"%.2f",percentComplete] delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
[alert show];
//Connessione download
DownloadRequest = [[NSURLRequest alloc] initWithURL:fileURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
DownloadConnection = [[NSURLConnection alloc] initWithRequest:DownloadRequest delegate:self startImmediately:YES];
}
else{
//Utente non inserisce il nome per il video
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:#"TubeDownloader" message:#"You have to insert a name for the video!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertview show];
}
}else {
//Non si riesce a prendere URL
UIAlertView *alertView1 = [[UIAlertView alloc] initWithTitle:#"TubeDownloader" message:#"Couldn't get MP4 URL." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView1 show];
[downloadButton setEnabled:YES];
}
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
if(!operationBreaked){
[self.receivedData appendData:data];
//[self.receivedData setData:data];
float receivedLen = [data length];
NSLog(#"receive lenght: %f\n",receivedLen);
bytesReceived = (bytesReceived + receivedLen);
if(expectedBytes != NSURLResponseUnknownLength){
//progressView.progress = ((bytesReceived/(float)expectedBytes)*100)/100;
percentComplete = (((bytesReceived/(float)expectedBytes)*100)/100) * 100;
}
NSLog(#"Ricevendo dati..percentuale di completamento:%f",percentComplete);
[alert setMessage:[NSString stringWithFormat:#"Percentage:%.2f",percentComplete]];
}else{
[connection cancel];
NSLog(#"Ricezione dati cancellata...percentuale:%f",percentComplete);
}
[self.receivedData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
operationFailed = YES;
//progressView.progress = 0.0;
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(#"Bytes aspettati: %f... Bytes ricevuti:%f\n",(float)expectedBytes,(float)bytesReceived);
NSHTTPURLResponse *r = (NSHTTPURLResponse*) response;//An NSHTTPURLResponse object represents a response to an HTTP URL load request. It’s a subclass of NSURLResponse that provides methods for accessing information specific to HTTP protocol responses.
NSDictionary *headers = [r allHeaderFields];//headerFields:a dictionary representing the keys and values from the server’s response header.
NSLog(#"[DO::didReceiveResponse] response headers: %#", headers);
if (headers){
if ([headers objectForKey: #"Content-Range"]) {
NSString *contentRange = [headers objectForKey: #"Content-Range"];
NSLog(#"Content-Range: %#", contentRange);
NSRange range = [contentRange rangeOfString: #"/"];
NSString *totalBytesCount = [contentRange substringFromIndex: range.location + 1];
expectedBytes = [totalBytesCount floatValue];
} else if ([headers objectForKey: #"Content-Length"]) {
NSLog(#"Content-Length: %#", [headers objectForKey: #"Content-Length"]);
expectedBytes = [[headers objectForKey: #"Content-Length"] floatValue];
} else expectedBytes = -1;
if ([#"Identity" isEqualToString: [headers objectForKey: #"Transfer-Encoding"]]) {
expectedBytes = bytesReceived;
operationFinished = YES;
}
}
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(#"connessione terminata con successo receive data:%f!!",bytesReceived);
operationFinished = YES;
[alert setMessage:#"Download been succesfully"];
app.networkActivityIndicatorVisible = NO;
//NSData *saveData = [NSData dataWithBytes:&receivedData length:sizeof(receivedData)];
//Attivo timer per dimettere il timer
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(dismissAlert) userInfo:nil repeats:NO];
//[self.receivedData setData:];
//Chiamo la funzione di salvataggio passandogli come NSData receivedata e localfileName
//[self saveVideo:self.receivedData];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *pathdir = [NSString stringWithFormat:#"%#.mp4", [[path objectAtIndex:0] stringByAppendingPathComponent:videoTitle]];
NSLog(#"pathDir: %#",pathdir);
[fileManager createFileAtPath:pathdir contents:receivedData attributes:nil];
NSString *imagePath = [NSString stringWithFormat:#"%#.mp4", [[path objectAtIndex:0]stringByAppendingPathComponent:videoTitle]];
AVAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:[NSString stringWithFormat:#"%#.mp4",[[path objectAtIndex:0] stringByAppendingPathComponent:videoTitle]]] options:nil]; //AVAsset is an abstract class to represent timed audiovisual media such as videos and sounds. Each asset contains a collection of tracks that are intended to be presented or processed together, each of a uniform media type, including but not limited to audio, video, text, closed captions, and subtitles.
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; //An AVAssetImageGenerator object provides thumbnail or preview images of assets independently of playback. AVAssetImageGenerator uses the default enabled video track(s) to generate images.
Float64 durationSeconds = CMTimeGetSeconds(asset.duration);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds / 2.0, 600);
CMTime actualTime;
CGImageRef preImage = [imageGenerator copyCGImageAtTime:midpoint actualTime:&actualTime error:NULL];
if (preImage != NULL) {
CGRect rect = CGRectMake(0.0, 0.0, CGImageGetWidth(preImage) * 0.5, CGImageGetHeight(preImage) * 0.5);
UIImage *image = [UIImage imageWithCGImage:preImage];
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
NSData *data = UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext());
[fileManager createFileAtPath:imagePath contents:data attributes:nil];
UIGraphicsEndImageContext();
}
CGImageRelease(preImage);
//videoTitle = nil;
NSLog(#"Salvataggio con successo");
}
I want to download multiple images from URL to my device in iOS App.
//
// ImageDownload.m
//
#import "ImageDownload.h"
#implementation ImageDownload {
int *position;
NSArray *downloableImages;
}
- (void)start:(NSArray *)images delegate:(id)delegate
{
position = 0;
downloableImages = images;
NSUInteger *count = ((NSUInteger *)[downloableImages count]);
NSLog(#"%d", count);
[self startDownload];
}
- (void)startDownload
{
NSUInteger *imageDataCount;
NSArray *image;
NSString *filename;
NSString *fileurl;
NSURLRequest *imageUrlRequest;
image = [downloableImages objectAtIndex:position];
NSLog(#"%d", position);
NSArray *imageData = [image valueForKey:#"image"];
imageDataCount = ((NSUInteger *)[imageData count]);
if (imageDataCount > 0) {
filename = [imageData objectAtIndex:0];
fileurl = [imageData objectAtIndex:1];
NSLog(#"%#", fileurl);
imageUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:fileurl]];
NSURLConnection *imageUrlConnection = [[NSURLConnection alloc] initWithRequest:imageUrlRequest delegate:self startImmediately:TRUE];
} else {
NSUInteger *count = ((NSUInteger *)[downloableImages count]);
if (((NSUInteger *)position) < ((NSUInteger *)count - 1)) {
position = position + 1;
[self startDownload];
}
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"finish image...");
NSUInteger *count = ((NSUInteger *)[downloableImages count]);
if (((NSUInteger *)position) < ((NSUInteger *)count - 1)) {
position = position + 1;
[self startDownload];
}
}
#end
For now... I only check the position of the download and current URL,
Exists 27 files to download... but the download not go one by one... check this output:
Position: 0
http.....fichero00.jpg
Finish download
Position: 4
http.....fichero04.jpg
Finish download
Position: 8
http.....fichero08.jpg
Finish download
Create an ivar NSOperationQueue *operationQueue; in your .h file and init it in your .m file:
operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 1;
For downloading images, create a method that takes an image URL and call it for each image:
-(void)downloadImageAtURL:(NSURL *)imageURL {
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:imageURL] queue:operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// Do something with your images here...
};
}
You can try this code.. Its 100 % Working for me
You can get more reference here
-(IBAction)startdownload
{
for (int i=0; i<[downloadarray count]; i++) //download array have url links
{
NSURL *URL = [NSURL URLWithString:[downloadarray objectAtIndex:i]];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc]initWithURL:URL];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if([data length] > 0 && [[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"])
{
//make your image here from data.
UIImage *imag = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [array objectAtIndex:0];
NSString *imgstr=[NSString stringWithFormat:#"%d",i];
NSString *pngfilepath = [NSString stringWithFormat:#"%#sample%#.png",docDir,imgstr];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(imag)];
[data1 writeToFile:pngfilepath atomically:YES];
}
else if ([data length] == 0 && [[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"])
{
NSLog(#"No Data!");
}
else if (![[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"]){
NSLog(#"Error = %#", error);
}
}];
}
-(IBAction)viewfile
{
NSMutableArray *arr=[[NSMutableArray alloc]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pngfilepath = [NSString stringWithFormat:#"%#",documentsDirectory];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:pngfilepath error:&error];
for (int i=0; i<[filePathsArray count]; i++){
NSString *pngfilepath = [NSString stringWithFormat:#"%#%#",documentsDirectory, [filePathsArray objectAtIndex:i]];
[arr addObject:[UIImage imageWithContentsOfFile:pngfilepath]];
}
myimageview = [[UIImageView alloc] initWithImage:[arr objectAtIndex:0]]; //Here myimageview is UIImageView
}
Hope This Helps!!!
Work around NSOperationQueue it allow you to control how much operation are run concurrently.
Create:
NSOperationQueue *queue = [NSOperationQueue new];
queue.maxConcurrentOperationCount = 1;
Then add operations :
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
... here is you code with converting image to data and addition it to NSURLConnection
}];
[operation setCompletionBlock:^{
....something that you want to do, after operation completes
}];
[queue addOperation:operation];
More about NSOperation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/cl/NSOperation
Here is my new code...
I have a delay when I try to update a UIProgressView
//
// ImageDownload.m
//
#import "ImageDownload.h"
#implementation ImageDownload {
NSMutableArray *downloableImages;
int position;
Sync *mySync;
}
- (void)start:(NSArray *)images sync:(Sync *)sync
{
NSArray *imageData;
int imageDataCount;
mySync = sync;
downloableImages = [[NSMutableArray alloc] init];
for (NSArray *image in images) {
imageData = [image valueForKey:#"image"];
imageDataCount = [imageData count];
if (imageDataCount > 0) {
[downloableImages addObject:imageData];
}
}
[self downloadAllFiles];
}
- (void)downloadAllFiles
{
NSString *filename;
NSString *fileUrl;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
position = 0;
int count = [downloableImages count];
NSLog(#"%#", downloableImages);
NSLog(#"total files %d", count);
for (NSArray *image in downloableImages) {
filename = [image objectAtIndex:0];
fileUrl = [image objectAtIndex:1];
NSURL *url = [NSURL URLWithString:fileUrl];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
position++;
float progress = (float)position / (float)count;
//update UIProgressView
[mySync setProgressImageDownload:progress];
if ([data length] > 0 && [[NSString stringWithFormat:#"%#", error] isEqualToString:#"(null)"]) {
UIImage *downloadedImage = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
NSString *imageDestinationPath = [NSString stringWithFormat:#"%#%#", cacheDirectory, filename];
NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(downloadedImage, 100.0)];
[imageData writeToFile:imageDestinationPath atomically:YES];
}
if (position == count) {
NSLog(#"all complete...");
[mySync downloadImagesComplete];
}
}];
}
}
#end
Hello i am using below framworks,
#import <MediaPlayer/MediaPlayer.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
In one of button event i have implemented below code to open Library.
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
mediaPicker.delegate = self;
mediaPicker.allowsPickingMultipleItems = YES; // this is the default
[self presentModalViewController:mediaPicker animated:YES];
[mediaPicker release];
And in delegate methods of MPMediaPickerController implemented code as below
#pragma mark MPMediaPickerController delegate methods
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
// We need to dismiss the picker
[self dismissModalViewControllerAnimated:YES];
// Assign the selected item(s) to the music player and start playback.
counterIpod = [mediaItemCollection.items count];
totalcollection = counterIpod;
if (totalcollection > 10) {
NSString *str = [NSString stringWithFormat:#"App Only supports importing 10 songs at a time"];
UIAlertView *connectionAlert = [[UIAlertView alloc] initWithTitle:#"Message !" message:str delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[connectionAlert show];
[connectionAlert release];
}
else {
[self performSelector:#selector(saveMediaItem:) withObject:mediaItemCollection afterDelay:0.1];
//[self saveMediaItem:mediaItemCollection];
//[self showLoadingView];
}
}
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
// User did not select anything
// We need to dismiss the picker
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark Sace Item Collection to documentsDirectory
-(void)saveMediaItem:(MPMediaItemCollection *)mediaItemCollection {
for (int i = 0; i < [mediaItemCollection.items count]; i++) {
[self exportAssetAsSourceFormat:[[mediaItemCollection items] objectAtIndex:i]];
NSLog(#"for loop : %d", i);
}
NSArray *itemsArray1 = appDelegate.mediaItemCollection1.items;
MPMediaItemCollection *mediaItemCollection2;
if ([itemsArray1 count] != 0) {
mediaItemCollection2 = [self collectionByAppendingCollection:mediaItemCollection];
}
else {
mediaItemCollection2 = mediaItemCollection;
}
[self saveMediaItemAfterDeletting:mediaItemCollection2];
}
-(void)saveMediaItemAfterDeletting:(MPMediaItemCollection *)mediaItemCollection {
NSMutableData* data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:mediaItemCollection forKey:#"my_playlist"];
[archiver finishEncoding];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/playlist.data", documentsDirectory];
NSLog(#"file path = %#", filePath);
[data writeToFile:filePath atomically:YES];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
NSLog(#"file exists : ===========>>>>>>>>>>>");
} else {
NSLog(#"file doesn't exist");
}
//NSLog(#"archiving playlist success = %d", success);
[archiver release];
[data release];
[self UpdateMediaCollection];
}
-(NSString*) getExtension:(MPMediaItem *)item {
// [self showLoadingView];
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
// JP
// AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
// initWithAsset:songAsset
// presetName:AVAssetExportPresetPassthrough];
NSArray *tracks = [songAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *track = [tracks objectAtIndex:0];
id desc = [track.formatDescriptions objectAtIndex:0];
const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
FourCharCode formatID = audioDesc->mFormatID;
//exportAudioMix.inputParameters = [NSArray arrayWithObject:exportAudioMixInputParameters];
//exportSession.audioMix = exportAudioMix;
NSString *fileType = nil;
NSString *ex = nil;
switch (formatID) {
case kAudioFormatLinearPCM:
{
UInt32 flags = audioDesc->mFormatFlags;
if (flags & kAudioFormatFlagIsBigEndian) {
fileType = #"public.aiff-audio";
ex = #"aif";
} else {
fileType = #"com.microsoft.waveform-audio";
ex = #"wav";
}
}
break;
case kAudioFormatMPEGLayer3:
fileType = #"com.apple.quicktime-movie";
ex = #"mp3";
break;
case kAudioFormatMPEG4AAC:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
case kAudioFormatAppleLossless:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
default:
break;
}
return ex;
}
#pragma mark Covert Item separate item collection and store songs into directory
- (void)exportAssetAsSourceFormat:(MPMediaItem *)item {
// [self showLoadingView];
NSLog(#"export asset called");
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
NSLog(#"\n>>>> assetURL : %#",[assetURL absoluteString]);
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
// JP
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:songAsset
presetName:AVAssetExportPresetPassthrough];
NSArray *tracks = [songAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *track = [tracks objectAtIndex:0];
id desc = [track.formatDescriptions objectAtIndex:0];
const AudioStreamBasicDescription *audioDesc = CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)desc);
FourCharCode formatID = audioDesc->mFormatID;
//exportAudioMix.inputParameters = [NSArray arrayWithObject:exportAudioMixInputParameters];
//exportSession.audioMix = exportAudioMix;
NSString *fileType = nil;
NSString *ex = nil;
switch (formatID) {
case kAudioFormatLinearPCM:
{
UInt32 flags = audioDesc->mFormatFlags;
if (flags & kAudioFormatFlagIsBigEndian) {
fileType = #"public.aiff-audio";
ex = #"aif";
} else {
fileType = #"com.microsoft.waveform-audio";
ex = #"wav";
}
}
break;
case kAudioFormatMPEGLayer3:
fileType = #"com.apple.quicktime-movie";
ex = #"mp3";
break;
case kAudioFormatMPEG4AAC:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
case kAudioFormatAppleLossless:
fileType = #"com.apple.m4a-audio";
ex = #"m4a";
break;
default:
break;
}
exportSession.outputFileType = fileType;
NSString *fileName = nil;
fileName = [NSString stringWithString:[item valueForProperty:MPMediaItemPropertyTitle]];
fileName = [[fileName stringByAppendingString:#"-"] stringByAppendingString:[item valueForProperty:MPMediaItemPropertyArtist]];
NSArray *fileNameArray = nil;
fileNameArray = [fileName componentsSeparatedByString:#" "];
fileName = [fileNameArray componentsJoinedByString:#""];
NSLog(#">>>>> fileName = %#", fileName);
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [[docDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:ex];
NSLog(#"filePath = %#", filePath);
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
//NSLog(#"file exist::::::::::==============>>>>>>>>>>>>>>>>>");
counterIpod--;
if(counterIpod == 0) {
//[self showAlertView];
//[self hideLoadingView];
}
NSString *str = [NSString stringWithFormat:#"Loading %d of %d Beats", totalcollection - counterIpod ,totalcollection];
[lbl performSelectorOnMainThread:#selector(setText:) withObject:str waitUntilDone:NO];
//NSLog(#"loading string : %#", str);
return;
}
//NSLog(#"file not exist ===========>>>>>>>>>");
// -------------------------------------
int fileNumber = 0;
NSString *fileNumberString = nil;
NSString *fileNameWithNumber = nil;
while ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
fileNumber++;
fileNumberString = [NSString stringWithFormat:#"-%02d", fileNumber];
fileNameWithNumber = [fileName stringByAppendingString:fileNumberString];
filePath = [[docDir stringByAppendingPathComponent:fileNameWithNumber] stringByAppendingPathExtension:ex];
//NSLog(#"filePath = %#", filePath);
}
// -------------------------------------
myDeleteFile(filePath);
exportSession.outputURL = [NSURL fileURLWithPath:filePath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSLog(#"export session completed");
counterIpod--;
NSString *str = [NSString stringWithFormat:#"Loading %d of %d Beats", totalcollection - counterIpod ,totalcollection];
//[self performSelector:#selector(setLabelText:) withObject:str afterDelay:0.02];
[lbl performSelectorOnMainThread:#selector(setText:) withObject:str waitUntilDone:NO];
NSLog(#"loading string : %#", str);
if(counterIpod == 0) {
//[self showAlertView];
//[self hideLoadingView];
}
} else {
NSLog(#"export session error");
counterIpod--;
NSString *str = [NSString stringWithFormat:#"Loading %d of %d Beats", totalcollection - counterIpod ,totalcollection];
[lbl performSelectorOnMainThread:#selector(setText:) withObject:str waitUntilDone:NO];
//return NO;
if(counterIpod == 0) {
//[self showAlertView];
//[self hideLoadingView];
}
}
[exportSession release];
}];
//[appDelegate hideLoadingView];
}
#pragma mark method to delete file from document directory
void myDeleteFile (NSString* path) {
// NSLog(#"file path delete file :::::::::: %#", path);
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSError *deleteErr = nil;
[[NSFileManager defaultManager] removeItemAtPath:path error:&deleteErr];
if (deleteErr) {
NSLog (#"Can't delete %#: %#", path, deleteErr);
}
}
}
Above code work without any error on iOS 4.0 or prior version but for iOS 5.0 is crashes on device, I can't resolve these issues since last 15 days.
Thanks in advance for Help.
I have solved this issues,
just comment out this line
fileName = [[fileName stringByAppendingString:#"-"] stringByAppendingString:[item valueForProperty:MPMediaItemPropertyArtist]];
because for some songs there is null artist so it's crash...................
This is because you are using some songs has artist name while some with blank artist name, so you are trying to append blank name in string that's why app going to crash.
Hope you unserstand what i say...