2012-04-09 7 views
1

AFNetworkingを使用して、URLからイメージを取り出し、サイズを変更し、ディスクに保存し、コアデータにパスを記録してから、テーブルビューとストアにロードします。コードが実行されると、UIがフリーズします。私はそれがダウンロードか私の悩みの原因となっている操作かどうか分からない。イメージダウンロードのためのAFNetworking、応答のないUI

私が使用しているコードは

- (void)getPhoto:(NSInteger)type forManagedObject:(MyManagedObject*)object { 

    // download the photo 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:object.photoUrl]]; 
    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request success:^(UIImage *image) { 


     // MyManagedObject has a custom setters (setPhoto:,setThumb:) that save the 
     // images to disk and store the file path in the database 
     object.photo = image; 
     object.thumb = [image imageByScalingAndCroppingForSize:CGSizeMake(PhotoBlockCellButtonWidth, PhotoBlockCellButtonHeight)]; 

     NSError *nerror; 
     if (![[DataStore sharedDataStore].managedObjectContext save:&nerror]) { 
      NSLog(@"Whoops, couldn't save: %@", [nerror localizedDescription]); 
      return; 
     } 

     // notify the table view to reload the table 
     [[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadTableView" object:nil]; 

    }]; 
    [operation start]; 
}

を下回っており、ここで私は、バックグラウンドスレッドにこれをプッシュしたいと思い、私の管理対象オブジェクト

- (NSString*)uniquePath{ 

    // prepare the directory string 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 

    // acquire a list of all files within the directory and loop creating a unique file name 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSArray *existingFiles = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:nil]; 
    NSString *uniquePath; 
    do { 
     CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault); 
     CFStringRef newUniqueIdString = CFUUIDCreateString(kCFAllocatorDefault, newUniqueId); 

     uniquePath = [[documentsDirectory stringByAppendingPathComponent:(__bridge NSString *)newUniqueIdString] stringByAppendingPathExtension:@"png"]; 

     CFRelease(newUniqueId); 
     CFRelease(newUniqueIdString); 
    } while ([existingFiles containsObject:uniquePath]); 

    return uniquePath; 
} 

- (NSString*)saveImage:(UIImage*)image{ 
    NSString *path = [self uniquePath]; 
    NSData *data = UIImagePNGRepresentation(image); 
    [data writeToFile:path atomically:YES]; 
    return [NSString stringWithFormat:@"file://%@",path]; 
} 

- (void) setPhoto:(UIImage *)image { 
    self.photoUrl = [self saveImage:image]; 
}

からセッターに関連するサンプルコードですしかし、私はAFNetworking、Core Data、およびMessagingがスレッドの安全性の点でどのような意味を持っているのかよくわかりません。どんな考え?

私の知る限り
+1

2つのこと:1) 'imageProcessingBlock'パラメータを取る' AFImageRequestOperation'クラスメソッドを使用し、そこに画像リサイズを行います。 2)私はコアデータに画像(またはデータの塊)を格納することをお勧めします。通常は画像URLを保存し、必要に応じてNSURLCacheやその他のメカニズムを使用してロードすることをお勧めします。 – mattt

+0

Mattさん、画像処理コードをimageProcessingBlockに移動してくれました。あなたのネットワーキングクラスを愛してください。 –

+0

'AFImageRequestOperation'は独自のスレッドを使用しているため、' [operation start] 'の実行は現在のスレッドをブロックしません。 – fabb

答えて

3

Mattの提案に基づいて、私は以下のように私の呼び出しを再加工してUIを改善しました。

- (void)getPhoto:(NSInteger)type forManagedObject:(MyManagedObject*)object { 

    // download the photo 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:object.photoUrl]]; 
    AFImageRequestOperation *operation = [AFImageRequestOperation 
     imageRequestOperationWithRequest:request 
     imageProcessingBlock:^UIImage *(UIImage *image) { 
      return [image imageByScalingAndCroppingForSize:CGSizeMake(PhotoBlockCellButtonWidth, PhotoBlockCellButtonHeight)]; 
     } 
     cacheName:nil 
     success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { 

      // MyManagedObject has a custom setters (setPhoto:,setThumb:) that save the 
      // images to disk and store the file path in the database 
      object.photo = image; 
      object.thumb = image; 

      NSError *nerror; 
      if (![[DataStore sharedDataStore].managedObjectContext save:&nerror]) { 
       NSLog(@"Whoops, couldn't save: %@", [nerror localizedDescription]); 
       return; 
      } 

      // notify the table view to reload the table 
      [[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadTableView" object:nil];                 
     } 
     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { 
      NSLog(@"Error getting photo"); 
     }]; 
    [operation start]; 
}
4

、間違ったであなたの要求を実行する方法:

[operation start]; 

あなたの代わりにNSOperationQueueに操作を追加する必要があります

NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init]; 
    [operationQueue addOperation:operation]; 

(あなたが正しくキューをメモリ・管理する必要があります) 。

このようにすると、リクエストは非同期で実行され、UIをブロックすることはなく、マルチスレッドを処理する必要はありません。

+0

+1私はバックグラウンドで私のすべてのサーバーアクセスを管理するために使用するNSOperationQueueを通じてgetPhotoを呼び出していることに気をつけました。 Mattのソリューションが助けになりました。 –

+0

これはフリーズの問題を解決します – ardavar

関連する問題