質問

I am downloading thousands of images asynchronously through AFNetworking an storing them in iDevice but my app goes slow down when errors shows on console "Response time out"

following is the code that I used to download images.

[NSThread detachNewThreadSelector:@selector(DownloadImages) toTarget:self withObject:nil];
 -(void)DownloadImages
{
 for(int i = 0; i<=4600;i++)
    {
        NSString *FrameSmall = [NSString stringWithFormat:@"myimageurl%i.png",i];
        [self setbuttonImg:FrameSmall];
    }
}
-(void)setbuttonImg:(NSString *)str    
{
NSArray* badWords = @[@":", @"/", @".",@" "];
NSMutableString* mString = [NSMutableString stringWithString:str];

for (NSString* string in badWords) {
    mString = [[mString stringByReplacingOccurrencesOfString:string withString:@""] mutableCopy];
}

NSString *encoded = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:encoded]];
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
requestOperation.responseSerializer = [AFImageResponseSerializer serializer];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString * documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    [self saveImage:responseObject withFileName:mString ofType:@"png" inDirectory:documentsDirectoryPath];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
     }];
[requestOperation start];
}

-(void) saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
if ([[extension lowercaseString] isEqualToString:@"png"]) {
    [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
} else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
    [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
} else {
    //  ALog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", extension);
}

}

役に立ちましたか?

解決

All of your images are being downloaded at the same time which isn't a good idea.

You can set the max concurrency with the operationQueue on the AFHTTPRequestOperationManager

http://cocoadocs.org/docsets/AFNetworking/2.0.0/Classes/AFHTTPRequestOperationManager.html#//api/name/operationQueue

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.operationQueue.maxConcurrentOperationCount = 5; //set to max downloads at once.

他のヒント

Best practice would be to only load images that your user is going to see immediately - so the ones in view only. Typically that means just storing the URL, then loading the image when its actually needed. Using just a custom category on UIImageView (AFNetworking provides a similar category) you can load an image into a custom table view cell using:

- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
              placeholderImage:(UIImage *)placeholderImage
                       success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
                       failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;

Here's an example with a custom wrapper around that category:

- (void)tableView:(UITableView *)tableView
  willDisplayCell:(GameTableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
  cell.backgroundColor = [UIColor clearColor];
  id game = [self.games objectAtIndex:indexPath.row];
  if([game isKindOfClass:[Game class]])
  {
    Game *aGame = (Game *)game;
    cell.titleLabel.text = aGame.gameName;
    cell.descriptionLabel.text = aGame.gameDescription;
    cell.playGameButton.layer.cornerRadius = 8.0F;
    [cell.imageView loadImageFromRemoteURL:aGame.imageURL
                       withPlaceholder:[UIImage imageFromAssetsNamed:@"game_icon"]
                     completionHandler:^(UIImage *fetchedImage, NSError *error)
     {
       if(nil == error)
       {
         aGame.image = fetchedImage;
         // Note: Need to set the image in an imageView somewhere on the main thread.
       }
     }];
  }
}

This means that only game cells on screen will have their images loaded rather than loading them all at once.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top