2

I am trying to play a video stored in Core data. After fetch it shows, there is an object and objects.video returns a value but the dataString prints out to be null. I am not sure what I maybe doing wrong. Is it a right way to play video or is there something I could have done better?

I have single object in Core Data.

I have stored as video as NSData in Core data. I want to get that stored video and play. Is there any other way I can do it?

_context =  [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Activity" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];
// Specify how the fetched objects should be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"level"
                                                               ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];


NSError *error = nil;
NSArray *fetchResults = [_context executeFetchRequest : fetchRequest error : &error];
if(fetchRequest == nil){
    NSLog(@"Nothing fetched");
}


for (Activity *objects in fetchResults){

    NSLog(@"%@",objects.video);
  prints->  External Data Reference: <self = 0x7bf48750 ; path = FF54B18E-10B3-4B04-81D4-55AC5E2141B9 ; length = 504426>


NSString *dataString = [[NSString alloc] initWithData:objects.video encoding:NSUTF8StringEncoding];
    NSLog(@"%@",dataString);
    NSURL *movieURL = [NSURL URLWithString:dataString];
    NSLog(@"%@",movieURL);
    _moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
    [_moviePlayer.view setFrame:CGRectMake (20, 20, 200 , self.view.bounds.size.height/2)];
    [self.view addSubview:_moviePlayer.view];
    [_moviePlayer play];

}
NSLog(@"%i",fetchResults.count);
Rosh
  • 169
  • 16
  • Can you give an example of a value that `objects.video` might have? Also, why is `objects.video` a binary attribute instead of a string? – Tom Harrington Oct 06 '15 at 18:02
  • 2
    When storing large assets like video files you should probably not use CoreData but store them directly to disk and only store the file url in your database. – Palle Oct 06 '15 at 18:14
  • http://stackoverflow.com/a/4546070/4475605 – Adrian Oct 06 '15 at 18:16
  • How are you setting the string for the URL? Also, check how you decode the object from objects.video - does it need to be encoded and decoded? Your for loop could also be causing trouble unrelated to your string problem. If fetchResults has 100 videos, you are alloc/init a new movie player for each enumeration loop and you'll run out of memory. – noobsmcgoobs Oct 06 '15 at 18:27
  • I have stored Video in Core data. I have already set the constraint of video size limit of 5MB. I have stored the video as NSData. How can I fetch that video from Core Data. – Rosh Oct 06 '15 at 19:20

1 Answers1

2

It will just be a binary property on the managed object. You call the property and it returns NSData. From there you can do whatever you want with the NSData while it is memory. Your problem is that you can't convert the NSData into a NSURL. A NSURL is a reference to data where NSData is the actual data.

What you need to do is store the video file on disk, outside of the SQLite file. Then store a reference to it (aka a url) in Core Data. That will allow you to use the video file with the movie player.

As others have said, storing the video in the SQLite file is a bad idea. It will wreck the performance of Core Data.

Update 1

Thanks. I have not saved the video directly to core data instead just copied the video url and saved it as string in core data. Should I create a different folder for the app to store the videos whenever I create a copy of the videos the users use so even if they delete the original video that was uploaded to core data, the copy remains intact and thus maintaining integrity of the Objects in Core Data.

Your comment is unclear. According to your question, you are storing the actual video in Core Data. Based on the output you showed, you stored the file in Core Data. Have you changed that? If so, you should store the video file in a known location and store the relative URL to that location in core data as a string. Then you build the full URL from that when you are ready to use it. Since the sandbox can change you can't store the entire URL as it will go stale.

Marcus S. Zarra
  • 46,571
  • 9
  • 101
  • 182
  • Thanks @ Marcus S. Zara. I have not saved the video directly to core data instead just copied the video url and saved it as string in core data. Should I create a different folder for the app to store the videos whenever I create a copy of the videos the users use so even if they delete the original video that was uploaded to core data, the copy remains intact and thus maintaining integrity of the Objects in Core Data. – Rosh Oct 06 '15 at 22:42
  • @ Marcus S. Zara . I previously saved the video on Core data but after your guidance I stored only the string of video filename in core data and fetch the video from url location. Thanks for the help – Rosh Oct 12 '15 at 17:21
  • 1
    Why wouldn't we just store the video data as external storage with core data? Wouldn't it save the data externally, achieving the same goals as if you were manually storing it on disk and referencing it? You simply would have to use a background context to load the data into memory as not to lock up the UI. – Above The Gods Jan 14 '17 at 01:56