2012-04-09 128 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

兩件事:1)使用帶有'imageProcessingBlock'參數的'AFImageRequestOperation'類方法,並在那裏進行圖像大小調整。 2)我會推薦_against_在Core Data中存儲圖像(或任何數據blob);通常存儲圖像url並使用'NSURLCache'或其他一些機制來根據需要加載它通常會更好。 – mattt 2012-04-17 22:06:27

+0

感謝馬特,我的圖像處理代碼移動到imageProcessingBlock幫助。順便去愛你的網絡課。 – 2012-05-23 19:19:13

+0

'AFImageRequestOperation'使用自己的線程,所以執行'[operation start]'應該*不*阻止當前線程。 – fabb 2014-02-11 13:19:26

回答

3

基於馬特的建議,我通過重新調用我的調用改進了用戶界面,如下所示。

- (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]; 

(你應該正確的內存管理的隊列) 。

通過這樣做,您的請求將以異步方式執行,它不會阻止用戶界面,也不需要處理多線程。

+0

+1我忽略提及,我已經通過NSOperationQueue調用了getPhoto,我使用它來管理後臺中的所有服務器訪問。馬特的解決方案幫助。 – 2012-05-23 19:30:12

+0

這解決了凍結問題 – ardavar 2013-04-15 23:00:17