Best way to handle many ASIHttpRequests and master data operations in ipad application

The current application that I am developing for the iPad includes processing many network requests and storing the processed results in the master data.

The following is a scenario - the application should upload images for the objects that I display in a grid that can display a total of 30 objects. Each object can consist of 15 PNG images (also in a grid). Due to the way the server is implemented (that is, I have not implemented it and cannot easily change it), each image needs to be requested separately, so I need to make up to 15 requests for an object compared to a single request for downloading only 15 images.

For each object, I currently use ASINetworkQueue to queue 15 image requests. As soon as the queue ends, I take a snapshot of the sketch of the object with its images for display in the grid, and then save all png files for the kernel data.

Currently, I run everything in the main thread, except for network requests that are processed by ASI asynchronously, but since there are so many requests, the user interface of the application is essentially blocked until all requests are processed and the results are stored in the main data.

One of the solutions I came across is operations with the main data and recordings in a separate stream or using a large central send. The other is only loading images for visible objects and loading the rest while scrolling through the user.

, . .

+3
3

, Core Data, ( ), "".

, NSOperationQueue, ASI-. - , . , 30 ( ), 15 . . , , , , NSBlockOperations, . , ...

// Loop through the objects
for (NSArray *objectParts in objectsToDownload) {

    // Create our Object
    Object *obj = [Object insertIntoManagedObjectContext:self.moc];

    // This is the block which will do the post processing for the object
    NSBlockOperation *processBlock = [NSBlockOperation blockOperationWithBlock:^{

        // Do post processing here, be very careful with multi-threading CoreData
        // it likely you'll need some class to dispatch you MOCs which have all
        // all the observers set up.

        // We're gonna assume that all the sub-images have been stored in a instance
        // variable:
        [obj performPostProcessing];

    }];

    // Given the list of 15 images which form each object
    for (NSURL *part in objectParts) {

        // Create the ASI request for this part
        ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:part];

        // Configure the request
        [request setDelegate:self];
        [request setDidFailSelector:@selector(partRequestDidFail:)];
        [request setDidFinishSelector:@selector(partRequestDidFinish:)];

        // Store the object in the UserInfo dictionary
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:obj, @"Object", nil];
        [request setUserInfo:userInfo];

        // Add it as a dependency
        [processBlock addDependency:request];

        // Add it to our network queue
        [networkQueue addOperation:request];
    }

    // Add the processBlock to our worker queue
    [workerQueue addOperation:processBlock];
}

, didFinish :

- (void)partRequestDidFinish:(ASIHTTPRequest *)request {
    // Remember this is one the main thread, so any heavy lifting should be 
    // put inside a block operation, and queued, which will complicate the 
    // dependencies somewhat, but is possible.

    // Get the result data
    NSData *data = [request responseData];

    // Get the object that it belongs to from the user info dic
    Object *obj = [[request userInfo] objectForKey:@"Object"];

    // Keep track of the partial data in the object
    [obj storePartialDataForPostProcessing:data];
}

, , - , NSObject. , (, , , MOC , :

// Fends a MOC suitable for use in the NSBlockOperations
- (NSManagedObjectContext *)moc {
    // Get a blank managed object context
    NSManagedObjectContext *aContext = [[UIApplication sharedApplication] managedObjectContext;
[aContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:aContext];
    return aContext;

}

- (void)mergeChangesFromMOC:(NSNotification *)aNotification {
    @try {
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:aNotification];
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:[aNotification object]];      
    }
    @catch (NSException * e) {
        NSLog(@"Stopping on exception: %@", [e description]);
    }
    @finally {}
}

- , , MOC . . , , .

, , . , 15 , .

+5

, 1 .

, , , .

:

  • , , UIImages, CPU.
  • , . , .
  • Blob CoreData, Core Data

NSOperationQueue : 1 ASIHTTPRequests ( , startAsynchronous) 1 1

0

, SDwebImage:

SDImageCache , - , . , .

[imageView setImageWithURL: [NSURL URLWithString: @ "http://www.domain.com/path/to/image.jpg" ]                  placeholderImage: [UIImage imageNamed: @ "placeholder.png" ]]

https://github.com/rs/SDWebImage

0
source

All Articles