How to convert ALAsset to NSData in Swift?

1.4k Views Asked by At

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

1

There are 1 best solutions below

0
Martin R On BEST ANSWER

There are two problems in your code:

  • rep.getBytes() writes the bytes to an existing buffer which must have been allocated with the required size. Your buffer created with var buffer: UInt8 = UInt8() has the size zero.
  • (As @Lame already said in a comment:) The return value of rep.getBytes() is the number of bytes written to the buffer, not a pointer to the data.

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
        // ...
    }
}