如何检查辅助线程中的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;
另外,如果这种解析方式不好,请告诉我!
答案 0 :(得分:0)
首先,您不应该使用这种方式从远程主机下载任何内容。 有许多类似AFNetworking,ASIHTTPRequest
的库可以解决CFNetwork或NSURLConnection以处理重定向,错误处理等问题。 所以你一定要转到其中一个(或者根据NSURLConnection实现你自己的)。
直接回答您的问题: 您应该使用某种标识符来计算下载的图像(即for循环迭代计数器),并通过+ [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);
});
}