getting ALAssets from photos library iOS - objective-c

I am trying to get the time, date and location from a movie i took on my iPhone/iPad This is the code i used
//i get the video picked and then save it to app but i think i am getting the movie's asset data before i save it.
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{ NSError *error;
else if (picker.sourceType ==UIImagePickerControllerSourceTypePhotoLibrary) {
NSURL * movieURL = [info valueForKey:UIImagePickerControllerMediaURL] ;
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:movieURL
resultBlock:^(ALAsset*asset) {
NSDate *myDate = [asset valueForProperty:ALAssetPropertyDate];
NSLog(#"Date: %#", myDate);
} failureBlock:^(NSError *error) {
NSLog(#"Error");
}];
NSData * movieData = [NSData dataWithContentsOfURL:movieURL];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *slash = [documentsDirectory stringByAppendingPathComponent:#"/"];
NSString *documentsDirectory2 = [slash stringByAppendingPathComponent:self.user.text];
NSString *documentsDirectory21 = [documentsDirectory2 stringByAppendingPathComponent:#"/Movie"];
if (![[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory21])
[[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory21 withIntermediateDirectories:NO attributes:nil error:&error];
NSString *fullPath = [documentsDirectory21 stringByAppendingPathComponent:[[self imageNameTextField]text]];
fullPath = [fullPath stringByAppendingFormat:#".mp4"];
[ movieData writeToFile:fullPath atomically:YES];
}
however myDate is logged as null
what am i doing wrong
I just tried this code also (added 10/11)
CGImageSourceRef source = CGImageSourceCreateWithURL( (CFURLRef)movieURL, NULL);
NSDictionary* metadata = (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source,0,NULL));
NSLog(#"image data %#", metadata);
but still metadata is null;
I read that videos don't have the same metadata as images. if this is true then how do I access the video metadata since I can see data tied to the video in photos.
any help would be greatly appreciated.
I have tried everything I could find on the internet to help me do this but nothing seems to work.
When I log my movieURL this is what I get
2016-10-13 09:58:51.045271 my little world app[2641:1388034] movieURL;file:///private/var/mobile/Containers/Data/Application/22A178E5-74C4- 48EF-B487-5E01321508AD/tmp/trim.04F0AC8A-2960-464D-8670-7E79662EAB9B.MOV
So since it is in a temporary file can I not get the metadata.
Does the Metadata exits in the movies NSData and can I get it from that?
I am pulling my hair out.

So I figured this out here is the code
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if (picker.sourceType ==UIImagePickerControllerSourceTypePhotoLibrary) {
NSURL * movieURL = [info valueForKey:UIImagePickerControllerMediaURL] ;
[self getMediaName:nil url:[info objectForKey:UIImagePickerControllerReferenceURL]];
}
}
- (void)getMediaName:(UIImage*)originalImage url:(NSURL*)url {
#try {
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *asset) {
if (asset == nil) return;
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
NSString *fileName = [assetRep filename];
NSDate *myDate = [asset valueForProperty:ALAssetPropertyDate];
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM-dd-yyyy"];
NSLog(#"%#",[dateFormatter stringFromDate:myDate]);
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *error) {
};
ALAssetsLibrary *library = [ALAssetsLibrary new];
[library assetForURL:url resultBlock:resultblock failureBlock:failureblock];
}
#catch (NSException *exception) {
}
}
you can use any valueForProperty

Related

Corrupted files downloaded from Amazon S3 using AFAmazonS3Client

I created an app that download a plist file from Amazon S3. I was using AFAmazonS3Client a client based in AFNetworking framework.
-(void) getFile:(NSString *)fileName{
self.s3Manager = [[AFAmazonS3Manager alloc] initWithAccessKeyID:#"..." secret:#"..."];
self.s3Manager.requestSerializer.region = AFAmazonS3SAEast1Region;
self.s3Manager.requestSerializer.bucket = #"verba";
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
documentsPath = [documentsPath stringByAppendingPathComponent:fileName];
NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:documentsPath append:NO];
[self.s3Manager getObjectWithPath:#""
outputStream:stream
progress:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"%f%% Downloaded", (totalBytesRead / (totalBytesExpectedToRead * 1.0f) * 100));
} success:^(id responseObject) {
NSLog(#"Download Complete");
} failure:^(NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Then I checked if the plist file was in document folder. And it was. So I tried to open plist file and the result was nil:
-(NSString*) loadListName:(NSString*)fileName{
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* filePath = [documentsPath stringByAppendingPathComponent:fileName];
NSDictionary *temp;
if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]){
temp = [NSDictionary dictionaryWithContentsOfFile:filePath];
} else {
NSLog(#"File not found.");
}
NSString *listName = [temp objectForKey:#"name"];
return listName;
}
So I tried to add plist file manually. I downloaded and copied it to the documents folder and then dictionaryWithContentsOfFile could open the file. So I suppose that plist file was corrupted when I download the file using AFAmazonS3Client.
What I am doing wrong ?
Update 1
I realize that every single file that I downloaded from S3 are corrupted. I don't know if I handle the NSOutputStream in the right way or maybe another stuff.
For some reason getObjectWithPath method from AFAmazonS3Manager is not working properly.
So I rewrite my method using AFHTTPRequestOperation directly from AFNetworking
- (void)downloadFile:(NSString *)fileName block:(void (^)(NSError *error))block {
NSString *urlString = #"https://[bucket].[server area].amazonaws.com/";
urlString = [urlString stringByAppendingPathComponent:fileName];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSSet *set = operation.responseSerializer.acceptableContentTypes;
if ([[fileName pathExtension] isEqualToString:#"m4a"]) {
NSLog(#"%# set as audio/mp4", fileName);
operation.responseSerializer.acceptableContentTypes = [set setByAddingObject:#"audio/mp4"];
} else if ([[fileName pathExtension] isEqualToString:#"png"]) {
NSLog(#"%# set as image/png", fileName);
operation.responseSerializer.acceptableContentTypes = [set setByAddingObject:#"image/png"];
} else if ([[fileName pathExtension] isEqualToString:#"plist"]) {
NSLog(#"%# set as application/x-plist", fileName);
operation.responseSerializer.acceptableContentTypes = [set setByAddingObject:#"application/x-plist"];
}
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *fullPath = [documentsPath stringByAppendingPathComponent:[url lastPathComponent]];
[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:fullPath append:NO]];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"bytesRead: %lu, totalBytesRead: %lld, totalBytesExpectedToRead: %lld", (unsigned long)bytesRead, totalBytesRead, totalBytesExpectedToRead);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if (block) {
block(nil);
}
NSLog(#"RES: %#", [[[operation response] allHeaderFields] description]);
NSError *error;
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:&error];
if (error) {
NSLog(#"ERR: %#", [error description]);
} else {
NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
long long fileSize = [fileSizeNumber longLongValue];
NSLog(#"%lld", fileSize);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (block) {
block(error);
}
NSLog(#"ERR: %#", [error description]);
}];
[operation start];
}
Be carefull cause in last versiĆ³n of Xcode, every time you restart your app in simulator, the documents folder is deleted

UIImage gives nil

I'm quite new to iOS development. My app gets a file over a network, writes it as image.png and later on reads and displays the image. However, the display part is not working as my UIImage object is always set to nil (on the iOS simulator). I've tried implementing other answers from stackoverflow, but no luck.
Here's my code to save the file:
//inside utility class for model
NSFileHandle * handle = nil;
//For first packet of new file request
if(CountFileParts == 1)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"image.png"];
NSLog(#"%#",appFile);
handle = [NSFileHandle fileHandleForWritingAtPath:appFile];
if(handle == nil)
{
[[NSFileManager defaultManager] createFileAtPath:appFile contents:nil attributes:nil];
handle = [NSFileHandle fileHandleForWritingAtPath:appFile];
}
}
//For other incoming packets of the same request
else
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"image.png"];
//NSLog(#"%#",appFile);
handle = [NSFileHandle fileHandleForUpdatingAtPath:appFile];
[handle seekToEndOfFile];
//NSLog(#"Writing continue in new file");
}
if(handle == nil)
NSLog(#"handle nil");
NSData * data = [str dataUsingEncoding:NSUTF8StringEncoding];
[handle writeData:data];
[handle closeFile];
if(index != -1 && index!= NSNotFound)
{
NSLog(#"Inside Bool");
self.isPlotReady = YES;//kvo in view-controller as shown below
self.isPlotReady = NO;
}
Here's my code to load the image file:
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:#"isPlotReady"])
{
self.isReady = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
[self updateUI];
}
}
-(void) updateUI
{
if(self.isReady)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
[self lsOwnDirectory:documentsDirectory];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"image.png"];
//NSLog(#"%#",appFile);
UIImage *img = [UIImage imageWithContentsOfFile:appFile];
if(img == nil)
NSLog(#"Couldn't find image");
else
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:img] ;
[self.view addSubview:imageView];
}
}
}
//Prints Directory contents of input directory
- (void) lsOwnDirectory:(NSString *) currentpath {
NSError * error = [[NSError alloc] init];
NSFileManager *filemgr;
filemgr = [[NSFileManager alloc] init];
//currentpath = [filemgr currentDirectoryPath];
NSLog(#"Current Directory Path : %#",currentpath);
NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:currentpath error: &error];
for(NSString * file in files){
NSLog(#"%#", file);
}
}
It alway's prints "Couldn't find image" corresponding to the if statement, but I've seen the file is still there (lsOwnDirectory prints directory contents). Maybe I'm doing something basic wrong here. Thanks in advance.

Loading Core Data From Large JSON Causing App To Crash

I'm attempting to populate CoreData from a JSON file that consists of 170,000 plus dictionaries. The parsing of the json goes quick but when I start trying to add to CoreData I'm blocking the main thread for a long time and then the app eventually crashes. It crashes when calling the method [UIDocument saveToUrl:forSaveOperation:completionHandler] Here is my code. If anyone has an idea of what's causing it to crash or a more efficient way to load CoreData that would be greatly appreciated.
#property (nonatomic, strong) UIManagedDocument *wordDatabase;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.wordDatabase) {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"Word Database"];
self.wordDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
}
}
- (void)setWordDatabase:(UIManagedDocument *)wordDatabase
{
if (_wordDatabase != wordDatabase) {
_wordDatabase = wordDatabase;
[self useDocument];
}
}
- (void)useDocument
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.wordDatabase.fileURL path]]) {
// does not exist on disk, so create it
[self.wordDatabase saveToURL:self.wordDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self prepopulateWordDatabaseWithDocument:self.wordDatabase];
}];
}
}
- (void)prepopulateWordDatabaseWithDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchQ = dispatch_queue_create("Word Fetcher", NULL);
dispatch_async(fetchQ, ^{
//Fetch the words from the json file
NSString *fileString = [[NSBundle mainBundle] pathForResource:#"words" ofType:#"json"];
NSString *jsonString = [[NSString alloc] initWithContentsOfFile:fileString encoding:NSUTF8StringEncoding error: NULL];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSArray *words = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
[document.managedObjectContext performBlock:^{
for (NSDictionary *dictionary in words)
{
[Word wordFromDictionary:dictionary inManagedObjectContext:document.managedObjectContext];
}
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
}];
});
dispatch_release(fetchQ);
}
What I ended up doing that stopped my app from crashing was allocating a new NSManagedObjectContext and peformed all my loading in the background. After saving I called my NSFetchedResultsController and the table repopulated.
- (void)prepopulateWordDatabaseWithDocument:(UIManagedDocument *)document
{
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.undoManager = nil;
backgroundContext.persistentStoreCoordinator = document.managedObjectContext.persistentStoreCoordinator;
[backgroundContext performBlock:^{
NSString *fileString = [[NSBundle mainBundle] pathForResource:#"words" ofType:#"json"];
NSString *jsonString = [[NSString alloc] initWithContentsOfFile:fileString encoding:NSUTF8StringEncoding error: NULL];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *parseError;
NSArray *words = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&parseError];
for (NSDictionary *dictionary in words)
{
[Word wordFromDictionary:dictionary inManagedObjectContext:backgroundContext];
}
NSError *loadError;
if ([backgroundContext save:&loadError]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self setupFetchedResultsController];
});
}
}];
}

data needs 10 min to load data into core-database

I am working with a core database to save my data that I get back from a webservice into my app. But this is very very slow. Any idea how this comes? What I do is the following. I have a class for getting the data from the webservice. like you can see over here.
GenkData.h
+ (NSArray *)getNews;
GenkData.m
+ (NSDictionary *)executeGenkFetch:(NSString *)query
{
query = [NSString stringWithFormat:#"%#", query];
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// NSLog(#"[%# %#] sent %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), query);
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error] : nil;
if (error) NSLog(#"[%# %#] JSON error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
// NSLog(#"[%# %#] received %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), results);
return results;
}
+ (NSArray *)getNews
{
NSString *request = [NSString stringWithFormat:#"http://www.krcgenk.be/mobile/json/request/news/type/ipad"];
return [[self executeGenkFetch:request] valueForKey:#"news"];
}
Then in my first view controller that shows up I have a method that for fetching my data in my core database.
- (void)fetchGenkDataIntoDocument:(UIManagedDocument *)document
{
NSLog(#"Fetch data");
dispatch_queue_t fetchQ = dispatch_queue_create("Genk fetcher", NULL);
dispatch_async(fetchQ, ^{
NSArray *news = [GenkData getNews];
[document.managedObjectContext performBlock:^{ // perform in the NSMOC's safe thread (main thread)
int newsId = 0;
//int trainingIndex = -1;
for (NSDictionary *genkInfo in news) {
NSLog(#"Begint met nieuwsitem");
newsId++;
[News newsWithGenkInfo:genkInfo inManagedObjectContext:document.managedObjectContext withNewsId:newsId];
NSLog(#"Einde met nieuwsitem");
}
}];
});
NSLog(#"einde fethdata");
}
Next I have a category of the NSManagerd object subclass of news where I do the following.
+ (News *)newsWithGenkInfo:(NSDictionary *)genkInfo
inManagedObjectContext:(NSManagedObjectContext *)context
withNewsId:(int)newsId
{
News *news = nil;
news = [NSEntityDescription insertNewObjectForEntityForName:#"News"
inManagedObjectContext:context];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd/MM/yyyy"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT+0:00"]];
NSDate *date = [dateFormatter dateFromString:[genkInfo objectForKey:NEWS_DATE]];
news.title = [genkInfo objectForKey:NEWS_TITLE];
news.date = date;
news.genk_description = [genkInfo objectForKey:NEWS_DESCRIPTION];
news.imgurl = [genkInfo objectForKey:NEWS_IMGURL];
news.shortdescription = [genkInfo objectForKey:NEWS_SHORTDESCRIPTION];
news.url = [genkInfo objectForKey:NEWS_URL];
news.imagecopyright = [genkInfo objectForKey:NEWS_IMAGECOPYRIGHT];
news.news_id = [NSNumber numberWithInt:newsId];
return news;
}
I am doing the following proces like 10 times for 10 different entities. All of those attributes are mostly strings. Still this takes up to 10 minutes to load in all the data. Can somebody help me ?
Kind regards.
Dima's answer of checking with the profiler helped me with this question and solved my problem

Saving images to a directory

Hi I want to save an image to a directory, I pass the NSData and do what I think will save the file in a directory I create but the problem is that it doesn't save. This is what I have so far. Why doesn't the initWithContentsOfURL:encoding:error: work, it returns null but the other method I used works? The main problem is WRITETOURL which returns a 0 which i think means that the information wasn't stored properly, any tips?
NSFileManager *fm = [[NSFileManager alloc] init];
NSArray * directoryPaths = [fm URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask];
NSLog(#"%#", directoryPaths);
NSURL* dirPath = nil;
dirPath = [[directoryPaths objectAtIndex:0] URLByAppendingPathComponent:[NSString stringWithFormat:#"photos.jpeg"]];
NSError* theError = nil;
[fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError];
UIImage* photoToStore = [UIImage imageWithData:photoToSave];
NSString *pathContainingPhoto = [[NSString alloc] initWithFormat:#"%#.jpeg", UIImageJPEGRepresentation(photoToStore, 1.0)];
NSError *error = nil;
BOOL OK = [pathContainingPhoto writeToURL:dirPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
NSLog(#"OK = %d", OK); //Returns 0
NSLog(#"%#", dirPath);
//WHY DOESNT THIS VERSION WORK?
// NSString *pathToFile = [[NSString alloc] initWithContentsOfURL:dirPath encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%#", pathToFile);
NSString* pathToFile = [NSString stringWithContentsOfURL:dirPath encoding:nil error:nil];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:pathToFile error:nil];
NSLog(#"%#", dirContents);
Do like this and int count in .h file and set its intial value count = 0; in viewDidLoad:
NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:#"Image_%d.png",count];
error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:stringPath]) // removing item it already exuts
{
[[NSFileManager defaultManager] removeItemAtPath:stringPath error:&error];
}
if(photoToSave) // nsdata of image that u have
{
[photoToSave writeToFile:stringPath atomically:YES];
}
count++; // maintaining count of images