将视频URL保存到Core Data

5
在我的应用程序中,我使用UIImagePickerController来录制视频。然后,我将摄像机卷中的视频URL保存到核心数据中,每当我想要播放它时,我都会拉出URL并这样做。但是,当从照片应用程序中删除视频时,它仍然可以播放几天。如果没有从照片应用程序中删除,则在几天后仍将被删除。如何将视频保存到我的应用程序文档中,并将其URL保存到核心数据中?以下是我目前使用的代码(它不起作用):
这是不起作用的zip文件:http://jmp.sh/v/w4gE5SXNiRd0d7tasc3U 这是现在可以正常工作的zip文件,没有错误:http://jmp.sh/v/tzyJU3nlc1qOPI9ZzDTF
 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
 NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
 // Handle a movie capture
 if (CFStringCompare((__bridge_retained CFStringRef)mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) {
 NSString *moviePath = [NSString stringWithFormat:@"%@", [[info objectForKey:UIImagePickerControllerMediaURL] path]];
 NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
 NSData *videoData = [NSData dataWithContentsOfURL:videoURL];

 AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
 _managedObjectContext = [appDelegate managedObjectContext];
 Video *video = [NSEntityDescription insertNewObjectForEntityForName:@"Video" inManagedObjectContext:_managedObjectContext];

 [video setVideoData:videoData];

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 int random = arc4random() % 1000;
 //[documentsDirectory stringByAppendingFormat:@"/vid1.mp4"]
 NSString *tempPath = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:@"vid%d%@%@.mp4", random, self.currentAthlete.first, self.currentAthlete.last]];
 BOOL success = [videoData writeToFile:tempPath atomically:NO];
 if (success == FALSE) {
 NSLog(@"Video was not successfully saved.");
 }
 else{
 [video setVideoURL:[NSString stringWithFormat:@"%@", tempPath]];
 }

 NSError *error = nil;
 if (![_managedObjectContext save:&error]) {
 }

 if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath)) {
 UISaveVideoAtPathToSavedPhotosAlbum(moviePath, self,
 @selector(video:didFinishSavingWithError:contextInfo:), nil);
 }
 }
 [self dismissViewControllerAnimated:YES completion:nil];
 }

你目前的实现遇到了什么问题? - Bhumeshwer katre
@Bhumeshwerkatre:我不想从照片应用程序中播放视频,我希望将视频保存在我的应用程序中,以便用户无法删除视频。 - Josue Espinosa
你正在将视频保存在文档目录中,因此仅在核心数据中保存该路径。不要保存从相机胶卷获取的视频URL。 - Bhumeshwer katre
@Bhumeshwerkatre:我尝试过了,但它不起作用。我会用那段代码更新我的问题。 - Josue Espinosa
检查一下我的答案,它会解决你的问题。 - Bhumeshwer katre
3个回答

6

Core Data本身。

在你声称不应该直接将大型二进制对象存储到Core Data Store之前,请等一下,我同意。你不应该这样做。

但是,Core Data有一个选项,可以使用外部存储来存储二进制数据,如果文件很大的话。

enter image description here

现在,如果文件很大,Core Data会负责保存文件并存储URL。

帮你管理数据文件。


请注意,如果您获取了一个具有NSData属性(从外部存储加载)的NSManageObjectsNSSet,那么可能会引发内存警告或应用程序崩溃。 - martinezdelariva
并非绝对如此,只有在对象被故障时才会使用内存。 - Abizern
当然。我的意思是在集合中展示数据时,即UITableView,所有的NSData属性都会被加载。此外,如果您正在处理图像并且需要调整其大小,则每个图像在内存中都有NSData属性和调整大小的UIImage。也许对于视频来说情况不同。 - martinezdelariva
有办法解决所有这些问题。 - Abizern
我已经添加了一个关于这个问题的提问,谢谢。http://stackoverflow.com/questions/22454280/how-to-free-memory-using-core-data-external-storage - martinezdelariva

3

不要创建这样的路径:

NSString *tempPath = [NSString stringWithFormat:@"%@/vid%d%@%@.mp4", documentsDirectory, random, self.currentAthlete.first, self.currentAthlete.last];

创建方式如下:

NSString *tempPath = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:@"vid%d%@%@.mp4", random, self.currentAthlete.first, self.currentAthlete.last]];

我的代码还有其他问题吗?在Xcode中没有任何错误,但我仍然无法运行它。 - Josue Espinosa
首先,您正在将视频数据保存到核心数据中,请不要这样做。只需将视频路径保存到核心数据中。然后将该路径保存到核心数据中。 - Bhumeshwer katre
我不确定你的意思是什么?如果视频不存在,我将如何从URL播放视频?难道我不必使用视频数据将其写入我的文档目录吗?你能展示一下你的意思吗? - Josue Espinosa
我给你提供了创建路径的正确方法。根据路径编写你的视频数据,它一定会被写入你的文档目录中。在播放时从保存的路径获取数据并播放。 - Bhumeshwer katre
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/42264/discussion-between-josue-espinosa-and-bhumeshwer-katre - Josue Espinosa
显示剩余2条评论

0

这段代码将NSData对象写入文档目录(您可以选择其他位置),并指定其URL,然后将相同的URL保存到核心数据中。

(.h)

    @property (nonatomic, retain) NSData *data;

(.m)

    NSString *docsDir;
    NSArray *dirPaths;

    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    docsDir = [dirPaths objectAtIndex:0];
    NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:[@"video_" stringByAppendingString:[NSString stringWithFormat: @"%d.mp4", 0]]]];

    [self.data writeToFile:databasePath atomically:YES];
    NSURL *videoURL = [NSURL fileURLWithPath:databasePath];

    if(videoURL)
    {
        //save url to core data 
    }

1
我认为这是一个不错的开始,但是当保存非常大的视频文件时,这会阻塞线程吗?也许将写入文件的操作包装在完成处理程序中,以确保仅在 URL 确定有效时继续进行,会提高回答的质量。 - Tommie C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接