1

NSOperationQueue を使用して同時ダウンロードを実行し、Core Data に挿入しています。

以下はコードです、私は使用しています

if(nil==queue)
{
    queue=[[NSOperationQueue alloc]init];
   [queue setMaxConcurrentOperationCount:5];
}
for (FileDetailsEntity *entity in array)
{
    InoFileDownloader *fileDownloader=[[InoFileDownloader alloc]initWithFileDetailsEntity:entity andDelegate:self];
    [queue addOperation:fileDownloader];
}


//InoFiledownloader.m file

- (void)mergeChanges:(NSNotification *)notification
 {
    appDelegate=(InoAppDelegate*)[[UIApplication sharedApplication]delegate];
    NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];

// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                              withObject:notification
                           waitUntilDone:YES];
}


-(void)start
 {
    @autoreleasepool {


    [self willChangeValueForKey:@"isExecuting"];
    self.isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];

    appDelegate=(InoAppDelegate*)[[UIApplication sharedApplication]delegate];

    NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] init];
    [ctx setUndoManager:nil];
    [ctx setPersistentStoreCoordinator: [appDelegate persistentStoreCoordinator]];


    // Register context with the notification center
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self
           selector:@selector(mergeChanges:)
               name:NSManagedObjectContextDidSaveNotification
             object:ctx];

    NSDictionary *taskID=[[NSDictionary alloc]initWithObjectsAndKeys:fileDetaislsEntity.fileId,@"fileId",nil];

    NSArray *arry=[[NSArray alloc]initWithObjects:taskID, nil];

    NSMutableDictionary *jsonRequest=[NSMutableDictionary new];

    [jsonRequest setValue:arry forKey:@"fileId"];

    jsonWriter = [[SBJsonWriter alloc] init];

    if(self.isCancelled)
        return;

    NSString *jsonString = [jsonWriter stringWithObject:jsonRequest];

    NSData *postData = [jsonString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

    if(self.isCancelled)
        return;


    NSURL *url = [NSURL URLWithString:@"http://192.168.4.247:8080/InnoApps/mobjobs/post/imageDownload"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"POST"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

    if(self.isCancelled)
        return;

    [request setHTTPBody:postData];
    NSHTTPURLResponse* response;
    NSError* error = nil;

    //  NSLog(@"File started to download for the file id %@",entity.fileId);

    if(self.isCancelled)
        return;

    //Capturing server response
    NSLog(@"started to download for file id--%@",fileDetaislsEntity.fileId);
    NSData* result = [NSURLConnection sendSynchronousRequest:request  returningResponse:&response error:&error];
    NSLog(@"finished downloading data for file id--%@",fileDetaislsEntity.fileId);
    // if(request)
    //     NSLog(@"File downloaded for the file id %@",entity.fileId);

    if(self.isCancelled)
        return;

    SBJSON *jsonParser=[SBJSON new];

    NSString *jsonStr=[[NSString alloc]initWithData:result encoding:NSUTF8StringEncoding];


    // if(response.statusCode!=0)
    NSDictionary *resultDic;

    if([response statusCode]!=0)
    {
        resultDic= [jsonParser objectWithString:jsonStr];
    }
    else
    {
        resultDic=nil;
    }

    //  NSLog(@"resultDic---%@",resultDic);

    NSMutableDictionary *imageDetails= [[resultDic objectForKey:@"image"] objectAtIndex:0];
    NSString *imageStr=[imageDetails objectForKey:@"imageBlob"];


    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"FileDetailsEntity" inManagedObjectContext:ctx];

    [fetchRequest setEntity:entity];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"taskId = %@ AND fileId=%@",fileDetaislsEntity.taskId,fileDetaislsEntity.fileId];

    [fetchRequest setPredicate:predicate];

    NSError *errorTmp=nil;
    NSArray *fileDetailsArray= [ctx executeFetchRequest:fetchRequest error:&error];

    if(errorTmp)
        NSLog(@"error in fetching filedetails array----%@",[errorTmp localizedDescription]);
    for(FileDetailsEntity *entity in fileDetailsArray)
    {
        [entity setFileData:[imageStr dataUsingEncoding:NSUTF8StringEncoding]];
    }




    if(self.isCancelled)
        return;

    NSError *errorForDataSaving;

    if(![ctx save:&errorForDataSaving])
        NSLog(@"failed to save data after downloading image ---%@",[error localizedDescription]);

    NSLog(@"data saved in db for file id--%@",fileDetaislsEntity.fileId);

    if(self.isCancelled)
        return;


    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];
    isExecuting = NO;
    isFinished = YES;
    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];

    [(NSObject*)self.delegate performSelectorOnMainThread:@selector(didFinishDownloadingFileWithFileId:) withObject:fileDetaislsEntity.fileId waitUntilDone:NO];



}

}


 -(BOOL)isConcurrent { return YES; }

 -(BOOL)isExecuting { return isExecuting; }

 -(BOOL)isFinished { return isFinished; }

 -(BOOL)isCancelled { return cancelled; }

その後、最大 15 または 20 の操作を実行するだけで、キューは実行されません。誰か教えてください。何がうまくいかないのですか。

4

2 に答える 2

2

操作を追加する前にキューを一時停止し、操作プールを追加した後、キューを再開するには su する必要があります...

これを試してください:

if(nil==queue)
{
    queue=[[NSOperationQueue alloc]init];
   [queue setMaxConcurrentOperationCount:5];
}

[queue setSuspended:YES];

for (FileDetailsEntity *entity in array)
{
    InoFileDownloader *fileDownloader=[[InoFileDownloader alloc]initWithFileDetailsEntity:entity andDelegate:self];
    [queue addOperation:fileDownloader];
}

[queue setSuspended:NO];

また、マージ変更メソッドで、次のように waitUntilDone に FALSE のフラグを付けるように変更します。

[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                          withObject:notification
                       waitUntilDone:FALSE];
于 2013-04-15T15:58:57.197 に答える
0

問題は、使用している可能性がありますNSURLConnection sendSynchronousRequest。これはほとんど常に悪い考えです。なぜなら、それはブロックするからです。つまり、とりわけ、コードを完全に停止させる可能性があります (まさに何が起こっているかのように聞こえます)。

人々は通常NSURLConnection sendSynchronousRequest、NSURLConnection を適切に、つまり非同期で使用する方法を恐れているか知らないために使用します。しかし、適切に使用することは難しくなく、実行する価値があります。

于 2013-04-15T16:07:01.190 に答える