2016-08-16 2 views
0

사진 폴더의 이미지로 차지하는 총 저장 공간을 계산하려고합니다. 나는 다음과 같이 코드를 작성했다. 나는 성공적으로 이미지를 가져올 수 있어요하지만,이 코드는 두 개의 문제가있다 - 언젠가 응용 프로그램 충돌을 얻을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

악기를 사용하여 메모리를 소비하는 것을 확인해 보셨습니까? –

+0

예, 앞뒤로하면서 누출 여부를 확인하기 위해 메모리를 실행했습니다. 정확한 포인트 – Shohrab

답변

0

비디오와 노래에 대한 스토리지를 계산해야합니다, 그래서 아래의 예제에서 GCD 부분을 제거하는거야. 또한 누출 여부를 확인하고 메모리 사용량을 확인하기 위해 Instruments를 실행해야하지만 내 생각에 당신은 직접 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'를 사용하여 액세스하고 저장주기를 피하십시오. –