I'am populating gallery assets in my custom app. In my app, apple live images are considered as videos. I explicitly write a video against apple live image. Some of my apple live images are correctly written as videos while i get error for some of my images.
NSError error description says: "the operation could not be completed. [cocoa error -1].
Following method returns error for some media objects:
PHAssetResourceManager's writeDataForAssetResource
following is my method that takes array of apple live identifiers and my custom object array as parameters and do the processing by finding the assets against passed apple live identifiers identifiers in custom objects array.
- (void)updateAssetsToVideoFromLivePhotos:(NSMutableArray*)array objectsArray:(NSMutableArray*) mediaObjectsArray withCompletionHandler:(void (^)(void))completionBlock {
PHFetchOptions *fetchOptions = [PHFetchOptions new];
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:array options:fetchOptions];
for (NSInteger i = 0; i < [fetchResult count]; i++) {
PHAsset *phAsset = [fetchResult objectAtIndex:i];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *assetID = phAsset.localIdentifier;
NSRange range = [assetID rangeOfString:#"/"];
if (range.location != NSNotFound) {
assetID = [assetID substringToIndex:range.location];
}
NSString *outputPath = [documentsDirectory stringByAppendingFormat:#"/%#.mp4", assetID];
BOOL videoExists = [[NSFileManager defaultManager] fileExistsAtPath:outputPath];
NSError * errorRef;
if (videoExists) {
[[NSFileManager defaultManager] removeItemAtPath:outputPath error:&errorRef];
}
NSURL *outputURL = [NSURL fileURLWithPath:outputPath];
NSArray *assetResources = [PHAssetResource assetResourcesForAsset:phAsset];
for (NSInteger j = 0; j < [assetResources count]; j++){
PHAssetResource* assetResource = [assetResources objectAtIndex:j];
if (assetResource.type == PHAssetResourceTypePairedVideo){
PHAssetResourceRequestOptions *requestOptions =[PHAssetResourceRequestOptions new];
[[PHAssetResourceManager defaultManager]
writeDataForAssetResource:assetResource
toFile:outputURL
options:requestOptions
completionHandler:^(NSError *error) {
if (!error){
for (NSInteger i = 0; i < [mediaObjectsArray count]; i++){
MyCustomObject *mediaObject = [mediaObjectsArray
objectAtIndex:i];
if ([mediaObject matchesAssetID:assetID]){
[mediaObject updateForAppleLivePhoto:
[outputURL absoluteString]];
break;
}
}
} else {
NSLog(#"%#",[error localizedDescription]);
}
}];
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"mediaUpdated" object:nil];
});
completionBlock();
}
Related
I had done for merging array of images to video.....Can anyone help me to make a movie using array of images and video.
Here I added the code for making array of image to video
NSError *error = nil;
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSHomeDirectory()
stringByAppendingPathComponent:#"Documents"];
NSString *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:#"Montage-Videos.mp4"];
if ([fileMgr fileExistsAtPath:videoOutputPath])
[fileMgr removeItemAtPath:videoOutputPath error:&error];
{
UIImage * img;
imageArray = [[NSMutableArray alloc]init];
videoURLArray = [[NSMutableArray alloc]init];
for (int i=0; i<[randomArray count]; i++) {
AVAsset *asset = [AVAsset assetWithURL:[randomArray objectAtIndex:i]];
if ([[randomArray objectAtIndex:i] isKindOfClass:[NSURL class]]) {
// Here I need to add video to the array for making video.
}
else{
img = [randomArray objectAtIndex:i];
[imageArray addObject:img];
}
}
UIImage *image ;
for (int i=0; i<[imageArray count]; i++) {
image = [imageArray objectAtIndex:0];
}
if ([imageArray count]>0) {
dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
[self writeImagesToMovieAtPath:videoOutputPath withSize:CGSizeMake(374, 456) withImage:image];
});
}
}
}
I am new to iOS sandbox. I am trying to list out all files within the device sandbox. I am not able to succeed it
My Code is
- (void)viewDidLoad {
NSLog(#"Files .. %#",[self showFiles]);
}
- (NSMutableArray *)showFiles
{
NSError *err = nil;
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *myPath = [myPathList objectAtIndex:0];
NSArray *dirContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:myPath error:&err];
if(err) NSLog(#"showFiles() - ERROR: %#",[err localizedDescription]);
NSMutableArray *filePaths = nil;
int count = (int)[dirContent count];
for(int i=0; i<count; i++)
{
[filePaths addObject:[dirContent objectAtIndex:i]];
}
return filePaths;
}
Thanks in advance
OK, you are getting nil as you are passing back an unallocated array object:
NSMutableArray *filePaths = nil;
You want:
NSMutableArray *filePaths = [NSMutableArray new];
However given you are copying the filenames into this array from dirContent, you may just as well return dirContent directly:
- (NSMutableArray *)showFiles
{
NSError *err = nil;
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *myPath = [myPathList objectAtIndex:0];
NSArray *dirContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:myPath error:&err];
if (!dirContent)
NSLog(#"showFiles() - ERROR: %#",[err localizedDescription]);
return dirContent;
}
One further note: You are getting the contents of the Caches folder, which will be empty by default, as far as I know.
I successfully test my in app purchase function and downloaded the content. However I am not sure of an right way to transfer it to Document folder. I tested with the code:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
for (SKDownload *download in downloads)
{
switch (download.downloadState) {
case SKDownloadStateActive:
NSLog(#"Download progress = %f",
download.progress);
NSLog(#"Download time = %f",
download.timeRemaining);
break;
case SKDownloadStateFinished:
[self downloadFromURL:download.contentURL];///<--This is the function.
break;
}
}
}
-(void)downloadFromURL: (NSURL *) temporaryURL {
NSString *folderName = [[temporaryURL path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:folderName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
NSData *downloadData = [[NSData alloc] initWithContentsOfURL:temporaryURL];
[downloadData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(#"Error in writing file %#' : \n %# ", filePath , writeError);
return;
}
NSLog(#"File successfully downloaded. Url is %#",fileURL.absoluteString);
//myFileURL = fileURL;
NSFileManager *filemgr;
NSArray *filelist;
int count;
int i;
filemgr =[NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:folder error:NULL];
count = [filelist count];
NSLog(#"file count %i",count);
for (i = 0; i < count; i++)
NSLog(#"%#", filelist[i]);
}
I get a #"File successfully downloaded. Url is %#" from the code above but NSLog(#"%#", filelist[i]); give me no content. What else is missing here? I found out about this link
but not sure how to incorporate into my code. Any pointer will be good.
Let's check:
-(void)downloadFromURL: (NSURL *) temporaryURL {
// at this time, file is downloaded successfully???
// I think you should check here
NSURL * temporaryURL;
NSFileManager *fm = [NSFileManager defaultManager];
BOOL existed = [fm fileExistsAtPath:temporaryURL.path];
if(existed) // file is existed
else // file is not existed == maybe download fails
}
I have used some ways to check MD5 after downloading files. But, it seems that checking too much files md5 always lead to memory warning or crash for low memory. Does someone have a good solution for this?
I have use method to check MD5 from Joel's Writings, and other methods from other posts, but all could not solve my problem.
NSInteger index = 0;
while (downloadQueue.count > 0) {
NSLog(#"%i files need to download.", downloadQueue.count);
NSLog(#"00: %u", [MenChecker get_free_memory]);
#autoreleasepool {
NSString *src = [downloadQueue objectAtIndex:index];
NSString *path = [self.storageRoot stringByAppendingPathComponent:[storageList objectAtIndex:index]];
NSString *md5 = [md5CheckList objectAtIndex:index];
BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:path];
if (isExist) {
NSString *md5OfData = nil;
CFStringRef fileMD5Hash = FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
if (fileMD5Hash) {
md5OfData = (__bridge NSString *)fileMD5Hash;
CFRelease(fileMD5Hash);
}
if ([md5OfData isEqualToString:md5]) {
[downloadQueue removeObjectAtIndex:index];
[storageList removeObjectAtIndex:index];
[md5CheckList removeObjectAtIndex:index];
}
else {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
ASIHTTPRequest *request_cover = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:src]];
[request_cover setDownloadDestinationPath:path];
[request_cover startSynchronous];
NSString *md5OfDataFile = nil;
CFStringRef dataFileMD5Hash = FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
if (dataFileMD5Hash) {
md5OfDataFile = (__bridge NSString *)dataFileMD5Hash;
CFRelease(dataFileMD5Hash);
}
if ([[NSFileManager defaultManager] fileExistsAtPath:path] && [md5OfDataFile isEqualToString:md5]) {
[downloadQueue removeObjectAtIndex:index];
[storageList removeObjectAtIndex:index];
[md5CheckList removeObjectAtIndex:index];
}
else {
index ++;
}
md5OfDataFile = nil;
}
md5OfData = nil;
}
else {
NSString *directory = [path stringByReplacingOccurrencesOfString:[NSString stringWithFormat:#"/%#", [path lastPathComponent]] withString:#""];
[[NSFileManager defaultManager] createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];
ASIHTTPRequest *request_cover = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:src]];
[request_cover setDownloadDestinationPath:path];
[request_cover startSynchronous];
request_cover = nil;
NSString *md5OfData = nil;
CFStringRef fileMD5Hash = FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
if (fileMD5Hash) {
md5OfData = (__bridge NSString *)fileMD5Hash;
CFRelease(fileMD5Hash);
}
if ([[NSFileManager defaultManager] fileExistsAtPath:path] && [md5OfData isEqualToString:md5]) {
[downloadQueue removeObjectAtIndex:index];
[storageList removeObjectAtIndex:index];
[md5CheckList removeObjectAtIndex:index];
}
else {
index ++;
}
md5OfData = nil;
}
if (index >= downloadQueue.count) {
index = 0;
}
}
I want to retrieve in an array of the name of the files in Resources folder that have the .html extension. I have done this:
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Resources"];
NSError *error = nil;
NSArray *documentArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
for (int i=0; i < [documentArray count] - 1; i++) {
NSLog(#"value %#", [documentArray objectAtIndex:i]);
}
But the for loop displays continously null. Anyone knows how can I get this task right? thank you
Don't use NSHomeDirectory. Use [[NSBundle mainBundle] resourcePath] to get path to app's resources.
Edited: here's your example code.
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSError *error = nil;
NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:resPath error:&error];
if (!error)
{
for (NSString * filename in filenames)
{
NSString *extension = [filename pathExtension];
if ([extension isEqualToString:#"html"])
{
NSLog(#"%#", filename);
}
}
}