2017-04-03 8 views
0

に記憶された拡大イメージでの作業中は、私はこのようなビューコントローラを有しています。高いメモリ使用量や良質tradeofsアレイ

この動作は次のようにする必要があります。 ユーザーが範囲スライダをスライドさせると、ImageViewの画像が画像の配列内の新しい画像に切り替わります。また、ユーザは、画像の品質を損なうことなく画像上でズーム操作を行うことができる。

//image array 
var images = [UIImage]() 

を私は1920×1920ピクセルのサイズと画像あたり約120キロバイトとUIImageの作成に48枚の画像をダウンロードしている:私はだから何

viewDidLoad上の画像アレイにイメージをダウンロードすることでしたダウンロードしたデータのオブジェクトと、次のように配列にそれらを保存:私はこの関数を作成したImageViewの内部の画像を変更するには

DispatchQueue.global().async { [weak self] in 
    let data = try? Data(contentsOf: url) 
    DispatchQueue.main.async { 
     if data != nil { 
      let img = UIImage(data: data!) 
      self?.images.append(img!) 
     } else { 
      ... 
     } 
    } 
} 

func updateImage(currentImage: UIImage) { 
    self.imageView.image = currentImage 
} 

ユーザーがrangeSliderのスライドを開始すると、アプリケーションのメモリ使用量が40 MBから700 MBになり、ユーザーがすべての画像を切り替えた後に増加を停止します。その後、ユーザーはメモリー使用量に影響を与えずにイメージ全体を前後に切り替えることができます。

しかし、画像を更新する前に少しサイズを変更すると、メモリの問題は解決されますが、ユーザーが少しズームすると画像は低品質になります。それでは、どのよう私はメモリリークを提供しないためのエレガントな方法でそれを達成するが、それでも最高の画像品質を使用することができます

@IBAction func scaleImage(_ sender: UIPinchGestureRecognizer) { 
    print(self.imageView.transform) 

    let tmp = self.imageView.transform.scaledBy(x: sender.scale, y: sender.scale) 

    if (tmp.a >= 0.99 || tmp.d >= 0.99) && (tmp.a < 2.5 || tmp.d < 2.5) { 
     self.imageView.transform = self.imageView.transform.scaledBy(x: sender.scale, y: sender.scale) 
     sender.scale = 1 

     if (tmp.a <= 1.2 || tmp.d <= 1.2) { 
      self.imageView.center = defaultImageCenter 
     } 
    } 
} 

extension UIImage { 
    func resized(_ newSize:CGSize) -> UIImage { 
     UIGraphicsBeginImageContextWithOptions(newSize, false, 0) 
     self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)) 
     let newImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     return newImage! 
    } 
} 

func updateImage(currentImage: UIImage) { 
    let currentImg = currentImage.resized(self.imageView.bounds.size) 

    self.imageView.image = currentImg 
} 

そして、私はこれを使用するズーム用:一部のサイズを変更

?この部分では、代わりにUIImageを作成し、アレイに追加の

+0

同時にダウンロードする必要はありますか? –

+0

はい、それは遅れているコンテンツなしで優れたユーザーエクスペリエンスを持つ必要があるためです。 – Kingalione

+0

このようなことをするほとんどのアプリは、いくつかの画像を先に読み込みますが、一気に読み込むことはありません。 –

答えて

2
if data != nil { 
    let img = UIImage(data: data!) 
    self?.images.append(img!) 
} 

、単にアレイをディスクにデータを保存し、その位置を記憶します。スライダを動かすと、スライダの位置に合わせてUIImageを作成します。この方法では、一度に1つのUIImageがメモリにロードされます。

さらに速くしたい場合は、前と次の画像も読み込みます(たとえば、位置4にあり、画像3と5を読み込みます。次に、スライダを位置5に移動すると、イメージ - この時点でリリースイメージ3およびロード6)。これによりメモリフットプリントが大きくなりますが、スライダを動かすとすぐに画像が表示されます。

これを高速化するために一度にすべての画像をダウンロードしたくないかもしれませんが、それはメモリに関連していないので、これで十分です。

関連する問題