应用程序挂起从FTP加载JSON,序列化并保存到Core Data [iOS]

时间:2013-06-05 07:00:41

标签: ios json core-data ftp

可能我的问题看起来很奇怪,但是......(希望有人帮助我)

我从FTP加载一些数据有两种方法。有时应用程序会依赖这些方法。

  1. 检查互联网连接。
  2. 如果互联网可用:

    @interface Download : NSObject {
        NSOperationQueue *operationQueue;
    }
    
    ...
    
    if (!operationQueue) {
        operationQueue = [NSOperationQueue new];
    }
    
    NSInvocationOperation *operation1;
    operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadIngredientsFromJSON) object:nil];
    [operationQueue addOperation:operation1];
    
    NSInvocationOperation *operation2;
    operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadRecipesFromJSON) object:nil];
    [operation2 addDependency:operation1];
    [operationQueue addOperation:operation2];
    
    [operationQueue addObserver:self forKeyPath:@"operations" options:0 context:NULL];
    
  3. 方法 loadIngredientsFromJSON &的 loadRecipesFromJSON

    -(void) loadIngredientsFromJSON
    {
        NSInteger countInBase = [self dataCountInEntity:@"Ingredients"];
    
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"ftp://...Ingredients.json"]];
        NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    
        NSError *error = nil;
        if (!responseData) {
            return;
        }
    
        NSDictionary *ingredientsDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
        if (!ingredientsDictionary) {
           return;
        }
    
        //NSLog(@"%@", [ingredientsDictionary description]);
    
        NSArray *keys = [ingredientsDictionary allKeys];
        if (!countInBase && [ingredientsDictionary count]>0) {
        AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        for (int i=0; i<[ingredientsDictionary count]; i++) {
           id aKey = [keys objectAtIndex:i];
           NSArray *ingrData = [ingredientsDictionary objectForKey:[NSString stringWithFormat:@"%@", aKey]];
           NSArray *tmpArray = [NSArray arrayWithObjects:aKey, [ingrData objectAtIndex:0], [ingrData objectAtIndex:1], nil];
           Ingredients *ingredient = [NSEntityDescription insertNewObjectForEntityForName:@"Ingredients" inManagedObjectContext:appDelegate.managedObjectContext];
    
           ingredient.code = [NSNumber numberWithInteger:[[tmpArray objectAtIndex:0] integerValue]];
           ingredient.name = [tmpArray objectAtIndex:1];
           ingredient.units = [tmpArray objectAtIndex:2];
           ingredient.type = [NSNumber numberWithInt:1];
           [appDelegate.managedObjectContext save:nil];
        }
        }
    }
    
  4. ...

        - (void) loadRecipesFromJSON
        {        
           NSInteger missedCount = 0;
           NSInteger recipeCode = 0;
           NSString *recipesPath = @"ftp://...";
    
           do {
             recipeCode ++;
             NSString *recipeFileName = [NSString stringWithFormat:@"recipes/%05d.json", recipeCode];
             NSString *recipeFileFullPath = [recipesPath stringByAppendingString:recipeFileName];
    
             NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:recipeFileFullPath]];
             NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
             NSError *error = nil;
             if (!responseData) {
                missedCount ++;
                continue;
             }
             NSDictionary *recipeDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
             if (!recipeDictionary) {
                missedCount ++;
                continue;
             }
    
             AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    
             NSInteger recipeCount = [self isDataExistInEntity:@"Recipes" withCode:[[recipeDictionary objectForKey:@"recipeCode"] integerValue]];
        if (recipeCount == 0) {
            Recipes *recipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipes" inManagedObjectContext:appDelegate.managedObjectContext];
            recipe.code = [recipeDictionary objectForKey:@"recipeCode"];
            recipe.dateUpdated = [recipeDictionary objectForKey:@"dateEdited"];
            recipe.inCategory = [recipeDictionary objectForKey:@"inCategory"];
            recipe.name = [recipeDictionary objectForKey:@"recipe"];
            recipe.difficulty = [recipeDictionary objectForKey:@"difficulty"];
            recipe.personCount = [recipeDictionary objectForKey:@"personCount"];
            recipe.prepHour = [recipeDictionary objectForKey:@"prepHour"];
            recipe.prepMin = [recipeDictionary objectForKey:@"prepMin"];
            int seconds = ([recipe.prepMin intValue]*60)+([recipe.prepHour intValue] * 60 * 60);
            recipe.prepTime = [NSNumber numberWithInt: seconds];
            recipe.isPaid = [recipeDictionary objectForKey:@"isPaid"];
            recipe.comment = [recipeDictionary objectForKey:@"comments"];
    
            NSDictionary *ingredients = [recipeDictionary objectForKey:@"ingredients"];
            NSArray *keys = [ingredients allKeys];
            if ([keys count] > 0) {
                for (int i=0; i<[keys count]; i++) {
                    Join *join = [NSEntityDescription insertNewObjectForEntityForName:@"Join" inManagedObjectContext:appDelegate.managedObjectContext];
                    join.recipeCode = [recipeDictionary objectForKey:@"recipeCode"];
    
                    id aKey = [keys objectAtIndex:i];
                    join.ingredientCode = [NSNumber numberWithInteger:[aKey integerValue]];
    
                    NSString *str = [ingredients objectForKey:aKey];
                    double num = [str doubleValue];
                    join.count = [NSNumber numberWithDouble:num];
    
                    join.inCart = [NSNumber numberWithInt:0];
                }
            }
    
            NSDictionary *prepStages = [recipeDictionary objectForKey:@"prepStage"];
            keys = [prepStages allKeys];
            if ([keys count] > 0) {
                for (int i=0; i<[keys count]; i++) {
                    PrepStages *prepStage = [NSEntityDescription insertNewObjectForEntityForName:@"PrepStages" inManagedObjectContext:appDelegate.managedObjectContext];
                    prepStage.recipeCode = [recipeDictionary objectForKey:@"recipeCode"];
    
                    id aKey = [keys objectAtIndex:i];
                    prepStage.order = [NSNumber numberWithInteger:[aKey integerValue]];
                    prepStage.descriptions = [prepStages objectForKey:aKey];
    
                    //загрузка картинки
                    NSString *recipeImageName = [NSString stringWithFormat:@"recipeImages/%05d-%@.jpg", recipeCode, [NSNumber numberWithInteger:[aKey integerValue]]];
                    NSString *recipeImageFullPath = [recipesPath stringByAppendingString:recipeImageName];
                    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:recipeImageFullPath]];
                    if (request) {
                        NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    
                        if (responseData) {
                            UIImage *image = [UIImage imageWithData:responseData];
                            prepStage.image = image;
                        }
                    }
    
                }
            }
            [appDelegate.managedObjectContext save:nil];
        }
        else {
            missedCount ++;
            continue;
        }
    
        } while (missedCount < 10);
        }
    

    有时,在这两种方法之一中,应用程序挂起并控制冻结。

    任何人都可以给我一些建议,说明可能存在错误。

    我很困惑......

    EDITED

    我注意到有趣的事情:

    下载过程在应用运行时启动。它从服务器下载 Recipes 并将其插入CoreData。如果我点按食谱列表,我会使用appDelegate.managedObjectContext来获取数据。当想要插入数据时,下载也会使用appDelegate.managedObjectContext

    这可能包含问题吗?

0 个答案:

没有答案