2016-08-16 5 views
0

写真フォルダ内の画像で占有されている総容量を計算しようとしています。私は次のようにコードを書いています。私は正常に画像を取得することができていますが、このコードでは、2つの問題がある -ios - 写真フォルダ内の総画像サイズを計算する

  1. 写真が7000枚以上の画像がある場合は、いつかアプリがクラッシュを取得します。から、ログ私は のメモリの問題を理解しています。

  2. このコードを複数回実行すると、前後に6〜7時間後にアプリがクラッシュします。

いずれのアイデアも本当に役立ちます。私はあなただけではなく、それを実行するコードを派遣している理解していない個別

-(void)getPhotoSize{ 

    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [_allPhotos enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) { 
      if (idx<_allPhotos.count&&asset) { 

       [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { 
        float imageSize = imageData.length; 
        imageSize = imageSize; 
        data.totalPictureSize+=imageSize; 
         _currentPhotoAsset=asset; 
       }]; 
      } 
     }]; 
    }); 
} 
+0

Instrumentsを使ってメモリを消費しているのを確認しましたか? –

+0

はい、前後しながら、私は漏れをチェックするためにメモリを実行しました。正確なポイント – Shohrab

答えて

0

動画や曲のストレージを計算する必要があるので、私は以下のサンプルからのGCDの一部を除去するつもりです。インストゥルメントを実行してリークをチェックし、メモリを消費するものを調べる必要がありますが、私が推測することは、ivarに直接アクセスして暗黙的にサイクルを保持していることです。これを試してください:

-(void)getPhotoSize{ 
    for (PHAsset *asset in _allPhotos) { 
     typeof(self) __weak weakSelf = self; // weak reference to self to avoid retain cycle 
     [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { 
      typeof(self) __strong strongSelf = weakSelf; // strong reference to make sure self exists until the block finishes 

      float imageSize = imageData.length; 
      imageSize = imageSize; 
      strongSelf.data.totalPictureSize+=imageSize; 
      strongSelf.currentPhotoAsset=asset; 
     }];   
    } 
} 

ネストされたブロックを避けるために、これを通常のforループに変更しました。


迅速かつ汚い非同期バージョン

-(void)photoSizeWithCompletion:(void (^)(float))completion { 
    NSArray *assets = _allPhotos; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     float totalSize = 0; 
     for (PHAsset *asset in assets) { 
      [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { 
       totalSize += imageData.length; 
      }];   
     }    

     completion(totalSize); 
    }); 
} 

はこのようにそれを呼び出します。

[someObject photoSizeWithCompletion:^(float totalSize){ 
    // use the totalSize 
}] 

これは、ユーザーが[戻る]ボタンに当たったときのためにキャンセルをサポートしていません。しかし、キャンセル可能な非同期操作を行うには、宿題としてNSOperationQueueを調べておきます。 Appleのマニュアルoperation queues and concurrencyを確認してください。

+0

を見つけることができません。私がディスパッチしていない場合、UIがブロックされています。なぜ私はバックグラウンドスレッドでこれを実行しようとしました。 – Shohrab

+0

しかし、 'dispatch_sync'を実行しても、依然として呼び出し元スレッドがブロックされます。あなたは 'dispatch_async'を使うつもりでしたか? –

+0

'data'もivarのように見えるので、' strongSelf.data'を使ってそれにアクセスし、保持サイクルを避けてください。 –

関連する問題