5

SwiftのimagePickerControllerに「情報」がないだけなので、URLを取得してデータに変換してWebサービスに送信する方法がわかりません。

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {

  var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL!
  var videoFileURL = videoDataURL.filePathURL
  var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)")
}
4

4 に答える 4

7

Xcode 10 • Swift 4.2 以降

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    if let url = info[.mediaURL] as? URL {
        do {
            try FileManager.default.moveItem(at: url, to: documentsDirectoryURL.appendingPathComponent("videoName.mov"))
            print("movie saved")
        } catch {
            print(error)
        }
    }
}

Xcode 8.3 • スウィフト 3.1

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
    let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    if let fileURL =  info[UIImagePickerControllerMediaURL] as? URL {
        do {
            try  FileManager.default.moveItem(at: fileURL, to: documentsDirectoryURL.appendingPathComponent("videoName.mov")
            print("movie saved")
        } catch {
            print(error)
        }
    }
}

スイフト2

オプションのラップを解除するには、 if let を使用する必要があります。iOS8もNSData.dataWithContentsOfMappedFile廃止されました。NSData メソッド初期化子 contentOfURL を使用してみてください:

注: didFinishPickingMediaWithInfo 宣言を から に変更する必要もあります[NSObject : AnyObject][String : AnyObject]

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    if let fileURL = info[UIImagePickerControllerMediaURL] as? NSURL {
        if let videoData = NSData(contentsOfURL: fileURL) {
            print(videoData.length)
        }
    }
}

Rob が述べたように、データは非常に大きくなる可能性がありますが、ファイルをコピーする代わりに、次のようにファイルをドキュメント フォルダーに移動する必要があります。

let documentsDirectoryURL =  try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
if let fileURL =  info[UIImagePickerControllerMediaURL] as? NSURL {
    do {
        try  NSFileManagerdefaultManager().moveItemAtURL(fileURL, toURL: documentsDirectoryURL.URLByAppendingPathComponent("videoName").URLByAppendingPathExtension("mov"))
        print("movie saved")
    } catch {
        print(error)
    }
}
于 2015-10-17T17:03:43.087 に答える
7

いくつかの問題があります。

  1. 次の行を検討してください。

    var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL!
    

    これは の強制的なアンラップを行いinfo[UIImagePickerControllerMediaURL](これが の場合、アプリがクラッシュするため、これは悪いことですnil)、暗黙的にアンラップされた optional としてキャストしますNSURL!。それは意味がありません。条件付きアンラップを実行するだけです(および aNSURLではなく a にアンラップしますNSURL!):

    if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { ... }
    
  2. 次の行は次を呼び出しますfilePathURL

    var videoFileURL = videoDataURL.filePathURL
    

    ファイルの URL が必要な場合は、既にあるので、変換する必要はなく、代わりにvideoDataURL. 本当にパスが必要な場合は、次のpathメソッドを使用します。

    let videoPath = videoDataURL.path
    

    率直に言って、Apple は文字列パスの使用をやめさせようとしているので、元のパスを使用し、videoDataURLと の両方pathを使用しないでくださいfilePathURL

  3. あなたが使用しているdataWithContentsOfMappedFile

    var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)")
    

    本当に を使用したい場合dataWithContentsOfMappedFile、適切な Swift 構文は次のとおりです。

    let video = NSData(contentsOfMappedFile: videoPath!)
    

    ただし、dataWithContentsOfMappedFile推奨されていないため、代わりに次を使用する必要があります。

    let video = try NSData(contentsOfFile: videoPath!, options: .DataReadingMappedIfSafe)
    

    または、それを完全にバイパスしvideoPathて、次のことができます。

    let video3 = try NSData(contentsOfURL: videoDataURL, options: .DataReadingMappedIfSafe)
    

    明らかに、これらのtryレンディションは、doブロックを使用してcatchブロック内で実行する必要があります。

  4. ところで、上記のすべての例でわかるようにlet、可能な場合は を使用する必要があります。

--

率直に言って、まったくロードしないことをお勧めしNSDataます。でコピーするだけでNSFileManager、メモリをより効率的に使用できます。ビデオが長い場合、非常に大きくなる可能性があるため、特定の時点ですべてをメモリにロードすることは避けてください。

したがって、次のことができます。

if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL {
    do {
        // build your destination URL however you want
        //
        // let tempFolder = NSURL(fileURLWithPath: NSTemporaryDirectory())
        // let destinationURL = tempFolder.URLByAppendingPathComponent("test.mov")

        // or 

        let documents = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
        let destinationURL = documents.URLByAppendingPathComponent("test.mov")

        // but just copy from the video URL to the destination URL

        try NSFileManager.defaultManager().copyItemAtURL(videoDataURL, toURL: destinationURL)
    } catch {
        print(error)
    }
}

これを Web サービスにアップロードする場合はNSURLSessionUploadTask、ファイルまたはストリーム オプションを使用して を使用します。このリクエストの構成は別の問題ですが、理解していただければ幸いです。写真や特にビデオなどの大きなアセットでは、NSData避けられる可能性がある場合はアセットで をインスタンス化しないでください。

于 2015-10-17T17:14:48.010 に答える