iosswiftnsdataalasset

How to convert ALAsset to NSData in Swift?


I have tried to convert ALAsset to NSData in the following code:

        let assetUrl = NSURL(string: self.filename!)

        ALAssetsLibrary().assetForURL(assetUrl,
            resultBlock: { asset in
                let rep = asset.defaultRepresentation()

                var buffer: UInt8 = UInt8()
                var error: NSError?

                let from: Int64 = 0

                let length: Int = Int(rep.size())
                var buffered = rep.getBytes(&buffer, fromOffset: from, length: length, error: &error)

                let data = NSData(bytesNoCopy: &buffered, length: length, freeWhenDone: true)

                self.video = data
            }, // # 1
            failureBlock: { error in
                println("ReportPhoto::loadVideoFromAssetsLibrary() - Error while loading saved video from AssetsLibrary!")
            }
        )

But I am getting the following error message in the console (at # 1 in the code):

object 0x27d02ce8: pointer being freed was not allocated

I tracked the object mentioned in the error and found it, but I do not know what is the problem and how to solve it!

The object is a property inside the NSData object called _bytes


Solution

  • There are two problems in your code:

    The easiest way would be to create an NSMutableData object with the required size and pass its mutable data pointer to rep.getBytes():

    var error: NSError?
    let length = Int(rep.size())
    let from = Int64(0)
    let data = NSMutableData(length: length)!
    let numRead = rep.getBytes(UnsafeMutablePointer(data.mutableBytes), fromOffset: from, length: length, error: &error)
    

    Note also that the ALAssetsLibrary framework is deprecated as of iOS 9. If your minimum deployment target is iOS 8 or later then you can achieve the same with PHAsset and PHImageManager from the Photos framework:

    let fetchResult = PHAsset.fetchAssetsWithALAssetURLs([assetUrl!], options: nil)
    if let phAsset = fetchResult.firstObject as? PHAsset {
        PHImageManager.defaultManager().requestImageDataForAsset(phAsset, options: nil) {
            (imageData, dataURI, orientation, info) -> Void in
            // ...
        }
    }