2016-08-03 10 views
2

Ich schreibe eine iOS-Anwendung auf swift, die ein Video von einer URL herunterlädt und auf die Festplatte schreibt. Ich bekomme die Daten, aber bisher war es nicht erfolgreich, auf die Festplatte zu schreiben. Unten ist der Code:Swift Video NSData in Galerie schreiben

let yourURL = NSURL(string: "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_10mb.mp4") 
    //Create a URL request 
    let urlRequest = NSURLRequest(URL: yourURL!) 
    //get the data 
    var theData = NSData(); 
    do{ 
     theData = try NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: nil) 
    } 
    catch let err as NSError 
    { 

    } 

    try! PHPhotoLibrary.sharedPhotoLibrary().performChangesAndWait({()-> Void in 
     if #available(iOS 9.0, *) { 
      PHAssetCreationRequest.creationRequestForAsset().addResourceWithType(PHAssetResourceType.Video, data: theData, options: nil) 

      print("SUCESS"); 
     } else { 

     }; 

    }); 

ich folgende Fehlermeldung erhalte, jede Einsicht geschätzt:

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=-1 "(null)": file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-703.0.18.1/src/swift/stdlib/public/core/ErrorType.swift, line 54 
+0

Anstatt 'try!' Zu verwenden, verwenden Sie 'do' -try'-'catch' und drucken das resultierende' error' Objekt. Es kann Ihnen eine aussagekräftigere Fehlermeldung geben. – Rob

+0

Ich bekomme einen ähnlichen Fehler, wenn ich das versuche: Fehler Domain = NSCoaErrorDomain Code = -1 "(null)" – user2658229

+0

Ich bin neu in iOS-Programmierung, so dass ich noch lerne, wie ich gehe. Es tut mir leid, aber was ist localizedDescription und userInfo, auf die Sie sich beziehen? Und ja, die App hat angefordert und hat Zugriff auf die Fotothek. – user2658229

Antwort

0

Ein Problem ist, dass Sie das Video zu laden versuchen (was ziemlich groß sein kann) in dem Speicher in einer NSData. Es ist viel besser, wenn Sie stattdessen Dateien im persistenten Speicher zu und von Dateien streamen können. Sie können dies erreichen, indem Sie die Download-Aufgabe NSURLSession verwenden und nicht die veraltete Methode NSURLConnection, sendSynchronousRequest.

Mithilfe von NSURLSession Download-Aufgabe, vermeiden Sie versuchen, ein großes Video im Speicher auf einmal zu halten, und es wird stattdessen das Video direkt in den persistenten Speicher streamen. (Beachten Sie, verwenden Sie keine NSURLSession Daten Aufgabe, als dass die gleichen Speicherbedarf Probleme als veraltet Methode sendSynchronousRequest von NSURLConnection haben.)

Sobald die NSURLSession Download-Aufgabe der Download direkt auf den persistenten Speicher gestreamt hat, können Sie dann Verschieben Sie die Datei in die temporäre Datei und verwenden Sie dann addResourceWithType, wobei Sie wiederum eine Datei-URL anstelle einer NSData angeben.

Als ich das tat, dass (und das Hinzufügen einiger andere nützliche Fehlerprüfung), schien es gut zu funktionieren:

// make sure it's authorized 

PHPhotoLibrary.requestAuthorization { authorizationStatus in 
    guard authorizationStatus == .Authorized else { 
     print("cannot proceed without permission") 
     return 
    } 

    self.downloadVideo() 
} 

Wo:

func downloadVideo() { 
    let fileManager = NSFileManager.defaultManager() 

    // create request 

    let url = NSURL(string: "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_10mb.mp4")! 
    let task = NSURLSession.sharedSession().downloadTaskWithURL(url) { location, response, error in 
     // make sure there weren't any fundamental networking errors 

     guard location != nil && error == nil else { 
      print(error) 
      return 
     } 

     // make sure there weren't and web server errors 

     guard let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 else { 
      print(response) 
      return 
     } 

     // move the file to temporary folder 

     let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) 
      .URLByAppendingPathComponent(url.lastPathComponent!) 

     do { 
      try fileManager.moveItemAtURL(location!, toURL: fileURL) 
     } catch { 
      print(error) 
      return 
     } 

     // now save it in our photo library 

     PHPhotoLibrary.sharedPhotoLibrary().performChanges({ 
      PHAssetCreationRequest.creationRequestForAsset().addResourceWithType(.Video, fileURL: fileURL, options: nil) 
     }, completionHandler: { success, error in 
      defer { 
       do { 
        try fileManager.removeItemAtURL(fileURL) 
       } catch let removeError { 
        print(removeError) 
       } 
      } 

      guard success && error == nil else { 
       print(error) 
       return 
      } 

      print("SUCCESS") 
     }) 
    } 
    task.resume() 
} 

Hinweis, weil NSURLSession strenger ist darum, sicherzustellen, Wenn Sie keine unsicheren Anforderungen ausführen, aktualisieren Sie möglicherweise die (klicken Sie mit der rechten Maustaste darauf und wählen Sie "Öffnen als" - "Quellcode") und fügen Sie sie der Datei hinzu:

<dict> 
    <key>NSExceptionDomains</key> 
    <dict> 
     <key>sample-videos.com</key> 
     <dict> 
      <!--Include to allow subdomains--> 
      <key>NSIncludesSubdomains</key> 
      <true/> 
      <!--Include to allow HTTP requests--> 
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> 
      <true/> 
      <!--Include to specify minimum TLS version--> 
      <key>NSTemporaryExceptionMinimumTLSVersion</key> 
      <string>TLSv1.1</string> 
     </dict> 
    </dict> 
</dict> 

Aber als ich das alles gemacht habe, wurde das Video heruntergeladen und meiner Fotogalerie erfolgreich hinzugefügt. Und beachte, dass ich hier alle synchronen Anfragen ausgeschnitten habe (NSURLSession ist asynchron, wie auch performChanges), da du fast nie synchrone Anfragen ausführen willst (und sicherlich nie in der Hauptwarteschlange).