来自PHAsset url的NSInputStream - iOS照片框架

时间:2015-09-17 09:03:59

标签: ios nsinputstream photosframework

我正在尝试从AVURLAsset网址创建一个来自照片框架的视频文件(或来自PHAsset网址的照片)的NSInputStream。我的代码如下:

mAsset = [NSInputStream inputStreamWithFileAtPath:[murl path]];
[mAsset open];

网址为file:///var/mobile/Media/DCIM/100APPLE/IMG_0519.JPG

现在我读了

NSUInteger readLength = [mAsset read:(uint8_t *)data maxLength:maxSize];

返回的readLength为-1。我认为它与iOS照片资产的权限有关

如果这种方式不正确,我可以通过照片框架资产从视频或图像文件中流式传输数据。 任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:6)

虽然这个问题有点陈旧,但我将解释我是如何解决它的,因为我遇到了同样的问题,并且从未在互联网上找到任何与照片框架配合使用的解决方案。

由于Apple API的设计方式,确实无法直接从ALAsset和PHAsset源文件上传。因此,让我先讨论如何使用旧的(现在已弃用的)API - AssetsLibrary来解决这个问题。

ALAssetRepresentation有一个很棒的方法getBytes:fromOffset:length:error:可直接转换为NSInputStream的{​​{1}}。这为您提供了一些如何从read:maxLength:实例中添加流的选项 - 您可以create a bound pair of input and output streams,或者您可以选择使用subclassing NSInputStream更为棘手的路径。

因此,在使用照片框架方面,这为您提供了第一个解决方案:您可以尝试get an ALAsset URL from a PHAsset,然后再回过头来创建一个来自好旧ALAsset的流。是的,此URL转换未记录,是的,AssetsLibrary现已弃用,但嘿 - 这是一个选项。并且媒体上有一个article表明它确实是一个有效的解决方案。

现在让我们转到照片框架。

借助iOS 9,Apple引入了一个适合我们目的的新类ALAssetRepresentation。这是冗长的方法PHAssetResourceManager a)逐步为您提供资产数据块; b)它提供对这些底层数据资源的直接访问,并且如果照片存在于电话上(即不是来自iCloud),则不需要文件系统的任何额外空间。旁注:“b)”中的语句实际上没有记录,但在现实生活中证明是正确的 - 您可能会尝试填充设备的存储并调用此方法,它可以很好地工作。但是,requestDataForAssetResource:options:dataReceivedHandler:completionHandler:有一些注意事项 - 它以异步方式传递数据,并且数据块具有任意大小。这个新API看起来很简单,这是很容易理解的 - 使用Photos Framework,您可以使用与本地和iCloud资产相同的方法。但总而言之,这种新方法并不像PHAssetResourceManager NSInputStream方法那样很好地转换为getBytes:fromOffset:length:error:的界面。但是很简单,我们可以利用这种方法的一个特性使其对消费者友好,以便它看起来就像旧的ALAssetRepresentation方法一样。此方法getBytes:fromOffset:length:error:按顺序在串行队列中传递数据。这意味着我们可以使用bounded blocking queue创建一个看起来像requestDataForAssetResource:options:dataReceivedHandler:completionHandler:的同步方法。在我们有这样的方法之后,获取资产的字节非常容易。

实际上,这正是我在我的库PHAssetResourceInputStream中所做的。它需要从Photos Framework获取资产字节后面的所有繁重工作,并为您提供一个简单的API,所以我希望它对遇到同样问题的人有所帮助。

<强> TL; DR

func nextChunk() throws -> Data?会让你开心。