如何在数据加载到模型对象后打开视图控制器?

问题描述:

如何检查我的辅助线程中的NSData dataWithContentsOfURL解析是否完成?当每个图像完成后,我想打开我的视图控制器。之前没有。现在我可以直接打开我的视图控制器,有时如果我要快速我的表视图没有图像,因为他们还没有完成。有任何想法吗?如何在数据加载到模型对象后打开视图控制器?

以下代码发生在AppDelegate的didFinishLaunchingWithOptions中。我使用SBJSON框架进行分析。

(使用即时通讯在此项目中的故事板,以便有用于打开第一视图控制器无码)

代码:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"json_template" ofType:@"json"]; 
NSString *contents = [NSString stringWithContentsOfFile: filePath encoding: NSUTF8StringEncoding error: nil]; 
SBJsonParser *jsonParser = [[SBJsonParser alloc] init]; 
NSMutableDictionary *json = [jsonParser objectWithString: contents]; 
tabs = [[NSMutableArray alloc] init]; 
jsonParser = nil; 

//parsing json into model objects 
for (NSString *tab in json) 
{ 
    Tab *tabObj = [[Tab alloc] init]; 
    tabObj.title = tab; 

    NSDictionary *categoryDict = [[json valueForKey: tabObj.title] objectAtIndex: 0]; 
    for (NSString *key in categoryDict) 
    { 

     Category *catObj = [[Category alloc] init]; 
     catObj.name = key; 


     NSArray *items = [categoryDict objectForKey:key]; 

     for (NSDictionary *dict in items) 
     { 
      Item *item = [[Item alloc] init]; 
      item.title = [dict objectForKey: @"title"]; 
      item.desc = [dict objectForKey: @"description"]; 
      item.url = [dict objectForKey: @"url"]; 

      if([dict objectForKey: @"image"] != [NSNull null]) 
      { 

       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) 
           { 
            NSURL *imgUrl = [NSURL URLWithString: [dict objectForKey: @"image"]]; 
            NSData *imageData = [NSData dataWithContentsOfURL: imgUrl]; 

            dispatch_async(dispatch_get_main_queue(), ^(void) 
            { 
             item.image = [UIImage imageWithData: imageData]; 

            }); 
           }); 
      } 
      else 
      { 
       UIImage *image = [UIImage imageNamed: @"standard3.png"]; 
       item.image = image; 
      } 

      [catObj.items addObject: item]; 

     } 

     [tabObj.categories addObject: catObj]; 
    } 

    [tabs addObject: tabObj]; 


} 

//sort array 
[tabs sortUsingComparator:^NSComparisonResult(id obj1, id obj2){ 


    Tab *r1 = (Tab*) obj1; 
    Tab *r2 = (Tab*) obj2; 

    return [r1.title caseInsensitiveCompare: r2.title]; 

}]; 



/***** END PARSING JSON *****/ 

[[UINavigationBar appearance] setTitleTextAttributes: @{ 
        UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetMake(0.0f, 0.0f)], 
        UITextAttributeFont: [UIFont fontWithName:@"GreatLakesNF" size:20.0f] 
}]; 

UIImage *navBackgroundImage = [UIImage imageNamed:@"navbar.png"]; 
[[UINavigationBar appearance] setBackgroundImage:navBackgroundImage forBarMetrics:UIBarMetricsDefault]; 
UIImage *backButtonImage = [[UIImage imageNamed:@"backBtn.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; 

UIImage *backButtonSelectedImage = [[UIImage imageNamed:@"backBtn_selected.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; 
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; 
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonSelectedImage forState: UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; 


return YES; 

另外,如果分析的这种方式不好,请告诉我!

首先,您不应该使用这种方式从远程主机下载任何内容。 有很多像AFNetworking库,ASIHTTPRequest

其解决CFNetwork的或NSURLConnection的处理这样的事情,重定向,错误处理等 所以你一定要移动到其中的一个(或实现自己的基于NSURLConnection的) 。

直接回答您的问题: 您应该使用某种标识符来计算下载图像(即for-loop迭代计数器),并通过+ [UINotificationCenter defaultCenter]作为某些自定义通知的参数传递它。

示例(假设你由+阻断当前线程[NSData的dataWithContentsOfURL:]):

for (int i = 0; i < 10; i++) { 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"someCustomNotificationClassName" object:nil userInfo:@{ @"counter" : @(i) }]; 
} 

更多基于NSNotification的方法的扩展的例子:

- (id)init { 
    self = [super init]; 
    if (self) { 
     // subscribing for notification 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDataDownload:) name:@"someCustomNotificationClassName" object:nil]; 
    } 

    return self; 
} 

- (void)dealloc { 
    // unsubscribing from notification on -dealloc 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

#pragma mark - downloading delegation 

- (void)handleDataDownload:(NSNotification *)notification { 
    NSDictionary *userInfo = [notification userInfo]; 
    int counter = [userInfo[@"counter"] intValue]; 
    if (counter == 10) { 
     // do some work afterwards 
     // assuming that last item was downloaded 
    } 
} 

您也可以使用回调技术来管理下载状态的处理:

void (^callback)(id result, int identifier) = ^(id result, int identifier) { 
    if (identifier == 10) { 
     // do some work afterwards 
    } 
}; 

for (int i = 0; i < 10; i++) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, kNilOptions), ^{ 
     // some downloading stuff which blocks thread 
     id data = nil; 
     callback(data, i); 
    }); 
}