2017-02-28 6 views
0

ディレクトリからデータを取得するためにWebサービスを使用するアプリケーションを作成しようとしていますが、デバイスにデータを保存してイメージを保存する必要があります。AlamofireおよびWebサービスを使用するためのAlamofireImageフレームワーク。生成されたオブジェクトをRealmフレームワークのデータベースに保存し、画像の場合はUIImageをファイルに保存します。Swiftを使用してバックグラウンドスレッドにファイルを保存する方法は?

基本的に、ViewControllerにはデータを表示するtableViewがありますが、ファイルに書き込む画像のために遅いです。

これは私の書き込み機能である:

func saveImage(_ image: UIImage) { 
    if let data = UIImagePNGRepresentation(image) { 
     let name = "images/person_directory_\(id).png" 
     let docsDir = getDocumentsDirectory() 
     let filename = docsDir.appendingPathComponent(name) 
     let fm = FileManager.default 

     if !fm.fileExists(atPath: docsDir.appendingPathComponent("images").path) { 
      do { 
       try fm.createDirectory(at: docsDir.appendingPathComponent("images"), withIntermediateDirectories: true, attributes: nil) 
       try data.write(to: filename) 
       try! realm?.write { 
        self.imageLocal = name 
       } 
      } 
      catch { 
       print(error) 
      } 
     } 
     else { 
      do { 
       try data.write(to: filename, options: .atomic) 
       try! realm?.write { 
        self.imageLocal = name 
       } 
      } 
      catch { 
       print(error) 
      } 

     } 
    } 
} 

Alamofireは画像

if person.imageLocal != nil, let image = person.loadLocalImage() { 
     print("Load form disk: \(person.imageLocal)") 
     cell.imgProfile.image = image 
    } 
    else if !(person.image?.isEmpty)! { 
     Alamofire.request(person.image!).responseImage(completionHandler: { (response) in 
      if response.result.isSuccess { 
       if let image = response.result.value { 
        person.saveImage(image) 
        cell.imgProfile.image = image 
        print("Downloaded: \(person.imageLocal)") 
       } 
      } 
     }) 
    } 

をダウンロードしかし、スクロールするときのtableViewがラグに見えると私は書き込みをしようとしたとき、私はこの関数を呼び出しますアプリケーションを別のスレッドに変更すると、アプリケーションのパフォーマンスに影響を与えずに書き込むことができます。DispatchQeue

DispatchQueue.global(qos: .background).async { 
        do { 
         try data.write(to: filename) 
        } 
        catch { 
         print(error) 
        } 
       } 

でも、アプリケーションはまだ遅いです。

はUPDATE:ロブが提案されているよう

は、私はこれをしようと試み:

func saveImage(_ image: UIImage) { 
    if let data = UIImagePNGRepresentation(image) { 
     let name = "images/person_directory_\(id).png" 
     do { 
      try realm?.write { 
       self.imageLocal = name 
      } 
     } 
     catch { 
      print("Realm error") 
     } 
     DispatchQueue.global().async { 
      let docsDir = self.getDocumentsDirectory() 
      let filename = docsDir.appendingPathComponent(name) 
      let fm = FileManager.default 

      if !fm.fileExists(atPath: docsDir.appendingPathComponent("images").path) { 
       do { 
        try fm.createDirectory(at: docsDir.appendingPathComponent("images"), withIntermediateDirectories: true, attributes: nil) 
       } 
       catch { 
        print(error) 
       } 
      } 
      do { 
       try data.write(to: filename) 
      } 
      catch { 
       print(error) 
      } 
     } 
    } 
} 

私はマルチスレッドをセンターサポートしませんレルムbecase書き込みレルムを派遣することはできません。 それでもスクロールは遅くなりますが、初めてのことはありません。だから、

+0

バックグラウンドで正しいコードを記述しているため、この質問にタイトルを調整することができます。 – Mozahler

+1

「遅い」とはどういう意味ですか?あなたのメインスレッドが遅くなっています。つまり、テーブルが面白いのですか?それとも、テーブルに画像が表示されないのですか?私が見るものは、あなたがAlamoFireのテーブルセルへの参照を保持しているということです。request()closure - たくさんのセルがあり、そのセルがスクロールすると、そのセルが再利用される可能性があります。たぶん、代わりにセルのインデックスを保持し、画像を取得したらセルをリロードしてください。 – joeybladb

+0

joeybladbの質問を拡大するには、画像がすぐに表示されないという問題があります(これは、[prefetchDataSource'](https://developer.apple.com/reference/uikit/uitableview/1771763 -prefetchdatasource))スクロールがスムーズではない(つまり、スッタリングする)のですか? – Rob

答えて

0

適切な答え@Robはそれが

DispatchQueue.global().async { 
     do { 
     try data.write(to: filename) 
     } 
     catch { 
     print(error) 
     } 
    } 

しかし、同様に重要である与えたように、非同期呼び出し(再び信用@Rob)からのUITableViewCellへの参照を使用しないことです。たとえば、コードの非同期部分からセル値を設定します。

   cell.imgProfile.image = image 

UITableViewCellsが再利用されるため、元のセルが同じインデックスで使用されていることがわかりません。テストのために、リストが本当に速くスクロールしてイメージが読み込まれるようにします。イメージが間違ったセルに表示された場合は、その再利用の問題です。

したがって、非同期コールバックから、新しいイメージのセルインデックスが表示されているかどうかを調べる必要があります。そのインデックスの現在のセルを取得してイメージを設定します。インデックスが表示されていない場合は、インデックスをスクロールして表示するまで画像を保存/キャッシュします。その時点で、そのセルはUITableView.cellForRowAtIndexPathで作成され、そこにイメージを設定できます。

関連する問題