I'm trying to retrieve a video file I saved in the Photo Album in order to display it in a Table view controller. I have been looking for an answer but I can't seem to find one.
my function to save it to the Album looks like this:
#IBAction func saveToAlbum(_ sender: Any) {
UISaveVideoAtPathToSavedPhotosAlbum((completedMoviePath?.path)!, nil, nil, nil)
}
Seems like there is no function that could retrieve the video saved. Can someone please guide me into it?
use like this it's working for me fine in swift 3
let library = ALAssetsLibrary()
let outputURL = UserDefaults.standard.object(forKey: "url")
if library.videoAtPathIs(compatibleWithSavedPhotosAlbum: outputURL as! URL!) {
library.writeVideoAtPath(toSavedPhotosAlbum: outputURL as! URL!,completionBlock: { (assetURL:URL?, error:Error?) -> Void in
//writeVideoAtPath(toSavedPhotosAlbum: outputURL,completionBlock: { (assetURL:URL!, error:Error?) -> Void in
var title = ""
var message = ""
if error != nil {
title = "Error"
message = "Failed to save video"
} else {
title = "Success"
message = "Video saved"
}
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
})
}
Related
I cannot find a way to import data from a CSV file. I want the data to be loading into an array.
I have tried Googling this but nothing I find seems to work for my case
This is my UIDocumentPickerViewController.
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
let urlst = "\(urls)"
if urlst.fileExtension() == "csv]" || urlst.fileExtension() == "csv" {
// Start Import Action From CSV File
} else {
let alert = UIAlertController(title: "An Error Occured!", message: "The file you were trying to inport is not supported. Only csv is support.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default , handler: nil))
alert.addAction(UIAlertAction(title: "Try Again", style: .default , handler: { (UIAlertAction) in
self.toImport()
}))
self.present(alert, animated: true, completion: nil)
}
}
My expected result is to get the csv file that the user selected using the UIDocumentPickerViewController and then importing it into an array or more then one. But I cannot find a way to make this work.
I finally found the solution to my problem. Here is the code:
let path = url.path
let importer = CSVImporter<exportDataImport>(path: path)
importer.startImportingRecords { recordValues -> exportDataImport in
return exportDataImport(name: recordValues[0], pricePer: recordValues[2], amount: recordValues[1], isComplte: recordValues[4], Qty: recordValues[3])
}.onFinish { importedRecords in
var tempArray = [exportDataImport]()
for record in importedRecords {
tempArray.append(record)
}
if tempArray.count > 0 {
tempArray.removeFirst(1)
self.importArray = tempArray
self.startImport()
}
}
I'm trying to load my data from dynamoBD and print them out with the labels.
Following the sample: https://github.com/awslabs/aws-sdk-ios-samples/tree/master/DynamoDBObjectMapper-Sample
I already created a table on the account and I can see their attributes using web browser.
Using this code to load data:
var tableRow: DDBTableRow?
func getTableRow() {
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
dynamoDBObjectMapper .load(DDBTableRow.self, hashKey: (tableRow?.PhotoId)!, rangeKey: tableRow?.UserId) .continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask!) -> AnyObject! in
if let error = task.error as? NSError {
print("Error: \(error)")
let alertController = UIAlertController(title: "Failed to get item from table.", message: error.description, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
} else if let tableRow = task.result as? DDBTableRow {
self.photoIdLabel.text = tableRow.PhotoId
self.userIdLabel.text = tableRow.UserId
self.photoDateLabel.text = tableRow.PhotoDate
self.photoURLLabel.text = tableRow.PhotoURL
self.photoCategoryLabel.text = tableRow.PhotoCategory
}
return nil
})
}
In the log: tableRows [MyProject.DDBTableRow]? nil none.
The sample code is working fine, I don't know what wrong. Do I miss something before calling load? I feel very close to solve it. Please help!
The layout of project architecture:
record audio -> trim audio -> play trimmed audio -> upload to server.
I'm having troubles with playback of audio file that is created as a result of AVAssetExportSession trimming. I had doubts about integrity of trimmed file and I've uploaded it to server and there it plays fine, but iOS refuses to play it. I init AVAudioPlayer with URL to trimmed file, then play() and nothing happens, not even errors are thrown.
Please see code below, what can cause the problem?
static func outputFileURL() -> URL {
let outputFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.path.appending("/audioRecord-trimmed.m4a")
return URL(fileURLWithPath: outputFileURL)
}
#IBAction func trimRecording(_ sender: RoundCornerButton) {
//Delete existing recording
deleteEditedRecording()
//Check duration
let duration = CMTimeGetSeconds(recordingToTrim.duration)
if (duration < 5.0) {
let alertController = UIAlertController(title: "Warning", message: "Sound is too short", preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil)
alertController.addAction(action)
self.present(alertController, animated: true, completion: nil)
return
} else {
let exporter = AVAssetExportSession(asset: recordingToTrim, presetName: AVAssetExportPresetAppleM4A)
exporter?.outputFileType = AVFileTypeAppleM4A
exporter?.outputURL = EditorVC.outputFileURL()
exporter?.timeRange = durationToTrim!
exporter?.exportAsynchronously(completionHandler: {
if exporter?.status == .completed {
let alertController = UIAlertController(title: "Success", message: nil, preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil)
alertController.addAction(action)
self.present(alertController, animated: true, completion: nil)
} else {
let alertController = UIAlertController(title: "Error", message: exporter?.error?.localizedDescription, preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil)
alertController.addAction(action)
self.present(alertController, animated: true, completion: nil)
print(exporter?.error?.localizedDescription)
print("Export failed")
return
}
})
}
}
#IBAction func playTrimmedAudio(_ sender: RoundCornerButton) {
print("\nPlay tap\n")
let player = try! AVAudioPlayer(contentsOf: EditorVC.outputFileURL())
player.play()
}
declare audio player globally like this :
var player:AVAudioPlayer!
in your playTrimmedAudio function add this two line of code
player = try! AVAudioPlayer(contentsOf: EditorVC.outputFileURL())
player.play()
I am building an app in Swift 2.3 and Xcode 8 and I need my app to query user information from a database (answers to questions they have answered earlier and saved in the database).
I have found some code (see it below) but I only get errors. I think that the problem is that code is looking for a specific item and I need to search the hash key for the unique id of the user so that every user who query's for their answers will get their specific information... any suggestions??
func updateAnswer() {
//first create expression
let queryExpression = AWSDynamoDBQueryExpression()
//second define the index name
queryExpression.indexName = "userID-index"
//3rd hashes
queryExpression.hashKeyAttribute = "userID"
queryExpression.hashKeyValues = ("us-east-1:97335bac-26d1-4b85-bc86-47091900df44")
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
//tableRow?.UserId --> (tableRow?.UserId)!
dynamoDBObjectMapper .query(Notes.self, expression: queryExpression) .continueWithExecutor(AWSExecutor.mainThreadExecutor(), withBlock: { (task:AWSTask!) -> AnyObject! in
if (task.error == nil) {
if (task.result != nil) {
let note = task.result as! Notes
self.driverAccomplishment1.text = note._content
}
} else {
print("Error: \(task.error)")
let alertController = UIAlertController(title: "Failed to get item from table.", message: task.error!.description, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: { (action:UIAlertAction) -> Void in
})
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
return nil
})
}
I have a variable videoURL of type NSURL.
If I call println(videoURL) it would return something like this:
http://files.parsetfss.com/d540f71f-video.mp4
I have a button set up that should take this videoURL and save the video to the user's camera roll.
The best I have done is this:
UISaveVideoAtPathToSavedPhotosAlbum(videoPath: String!, completionTarget: AnyObject!, completionSelector: Selector, contextInfo: UnsafeMutablePointer<Void>)
While I'm not even sure if this will work or not, I can't figure out how to convert videoFile:NSURL into a videoPath.
Any help is appreciated on this.
Edit:
The following is unsuccessful:
UISaveVideoAtPathToSavedPhotosAlbum(videoURL.relativePath, self, nil, nil)
AssetsLibrary is deprecated
1: import Photos
import Photos
2: Use this code to save video from url to camera library.
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(nsUrlToYourVideo)
}) { saved, error in
if saved {
let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
Swift 3 & Swift 4
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: urlToYourVideo)
}) { saved, error in
if saved {
let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
The accepted answer no longer works with Swift 3.0 & iOS 10.
First, you need to set the following permission in your app's plist file:
Privacy - Photo Library Usage Description
Provide a string that is presented to the user explaining why you are requesting the permission.
Next, import photos:
import Photos
Finally, here is the updated code for Swift 3.0:
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fileURL)
}) { saved, error in
if saved {
let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
To save video from NSURL to user camera roll
func video(videoPath: NSString, didFinishSavingWithError error: NSError?, contextInfo info: AnyObject)
{
if let _ = error {
print("Error,Video failed to save")
}else{
print("Successfully,Video was saved")
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let conversationField = self.conversation {
if (mediaType?.isEqual((kUTTypeMovie as NSString) as String))!
{
let theVideoURL: URL? = (info[UIImagePickerControllerMediaURL] as? URL)
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum((theVideoURL?.path)!))
{
UISaveVideoAtPathToSavedPhotosAlbum((theVideoURL?.path)!, self, #selector(ConversationDetailsViewController.video(videoPath:didFinishSavingWithError:contextInfo:)), nil)
}
}
self.dismiss(animated: true, completion: nil)
}
Reference from:: https://www.raywenderlich.com/94404/play-record-merge-videos-ios-swift
Try this instead for saving video in photo library in swift 4.2 and above
func requestAuthorization(completion: #escaping ()->Void) {
if PHPhotoLibrary.authorizationStatus() == .notDetermined {
PHPhotoLibrary.requestAuthorization { (status) in
DispatchQueue.main.async {
completion()
}
}
} else if PHPhotoLibrary.authorizationStatus() == .authorized{
completion()
}
}
func saveVideoToAlbum(_ outputURL: URL, _ completion: ((Error?) -> Void)?) {
requestAuthorization {
PHPhotoLibrary.shared().performChanges({
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .video, fileURL: outputURL, options: nil)
}) { (result, error) in
DispatchQueue.main.async {
if let error = error {
print(error.localizedDescription)
} else {
print("Saved successfully")
}
completion?(error)
}
}
}
}
Use of function
self.saveVideoToAlbum(/* pass your final url to save */) { (error) in
//Do what you want
}
Don't forgot to import Photos and add Privacy - Photo Library Usage Description to your info.plist
deprecated as of iOS 9
1: import AssetsLibrary
import AssetsLibrary
2: Use this code to save video from url to camera library.
ALAssetsLibrary().writeVideoAtPathToSavedPhotosAlbum(outputFileURL, completionBlock: nil)
Just use it and paste your video's url:
PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in
let createAssetRequest: PHAssetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(NSURL(string: /* your url */)!)!
createAssetRequest.placeholderForCreatedAsset
}) { (success, error) -> Void in
if success {
//popup alert success
}
else {
//popup alert unsuccess
}
}