I'm currently displaying a video in my app and I want the user to be able to save it to its device gallery/album photo/camera roll. Here it's what I'm doing but the video is not saved in the album :/
    func downloadVideo(videoImageUrl:String)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        //All stuff here
        print("downloadVideo");
        let url=NSURL(string: videoImageUrl);
        let urlData=NSData(contentsOfURL: url!);
        if((urlData) != nil)
        {
            let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0];
            let fileName = videoImageUrl; //.stringByDeletingPathExtension
            let filePath="\(documentsPath)/\(fileName)";
            //saving is done on main thread
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                urlData?.writeToFile(filePath, atomically: true);
                print("videoSaved");
            })
        }
    })
}
I'va also look into this :
let url:NSURL = NSURL(string: fileURL)!;
    PHPhotoLibrary.sharedPhotoLibrary().performChanges({
        let assetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(url);
        let assetPlaceHolder = assetChangeRequest!.placeholderForCreatedAsset;
        let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection)
        albumChangeRequest!.addAssets([assetPlaceHolder!])
        }, completionHandler: saveVideoCallBack)
But I have the error "Unable to create data from file (null)". My "assetChangeRequest" is nil. I don't understand as my url is valid and when I go to it with a browser, it download a quick time file.
If anyone can help me, it would be appreciated ! I'm using Swift and targeting iOS 8.0 min.
Update
Wanted to update the answer for Swift 3 using URLSession and figured out that the answer already exists in related topic here. Use it.
Original Answer
The code below saves a video file to Camera Roll. I reused your code with a minor change - I removed let fileName = videoImageUrl; because it leads to incorrect file path. 
I tested this code and it saved the asset into camera roll. You asked what to place into creationRequestForAssetFromVideoAtFileURL - put a link to downloaded video file as in the example below.
let videoImageUrl = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"
DispatchQueue.global(qos: .background).async {
    if let url = URL(string: urlString),
        let urlData = NSData(contentsOf: url) {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
        let filePath="\(documentsPath)/tempFile.mp4"
        DispatchQueue.main.async {
            urlData.write(toFile: filePath, atomically: true)
            PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
            }) { completed, error in
                if completed {
                    print("Video is saved!")
                }
            }
        }
    }
}
Swift 3 version of the code from @Nimble:
DispatchQueue.global(qos: .background).async {
    if let url = URL(string: urlString),
        let urlData = NSData(contentsOf: url)
    {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
        let filePath="\(documentsPath)/tempFile.mp4"
        DispatchQueue.main.async {
            urlData.write(toFile: filePath, atomically: true)
            PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
            }) { completed, error in
                if completed {
                    print("Video is saved!")
                }
            }
        }
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With