【发布时间】:2014-01-22 12:16:27
【问题描述】:
我正在开发一个消息客户端(如 Whatsapp 或 Line)。 我遇到了麻烦,因为我需要支持多个下载文件(和上传),在每条具有当前下载过程的消息中显示一个进度条。 多下载和上传过程已经开发(并且工作正常),当我尝试在消息进度栏中显示该进度时出现问题。
我的“解决方案”(不知道有没有更好的办法)是在CoreData的Message实体中添加一个“uploaded”和其他“downloaded”的字段,保存上传百分比或下载百分比,并在每次 NSURLConnection 调用时更新该字段(在上传过程中,在下载中不同):
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
但如果我尝试在该方法中更新 CoreData 上下文,我的用户界面就会冻结。
好的,那是我的问题,我给你看代码:
-
这是我的核心数据消息实体:
@property (nonatomic, retain) NSString *ident; @property (nonatomic, retain) NSString *localId; @property (nonatomic, retain) NSString *body; @property (nonatomic, retain) NSString *contentSize; @property (nonatomic, retain) NSNumber *uploaded; @property (nonatomic, retain) NSNumber *downloaded; @property (nonatomic, retain) Avatar *avatar; @property (nonatomic, retain) Thumbnail *thumbnail; -
这是我的类来管理每个 HTTP 连接,在这里我尝试更新该实体。
@implementation HTTPConnection //SOME CODE... - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { if (self.localId) { float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite; [self performSelectorOnMainThread:@selector(saveProgressInDatabase:) withObject:[NSNumber numberWithFloat:progress] waitUntilDone:YES]; } } - (void)saveProgressInDatabase:(NSNumber *)progress { NSManagedObjectContext *context = [[[AppDelegate alloc]init]managedObjectContext]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:MESSAGE_ENTITY inManagedObjectContext:context]; [fetchRequest setEntity:entity]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"localId = %@", self.localId]; [fetchRequest setPredicate:predicate]; NSError *coreError = nil; NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&coreError]; Message *currentMessage = [fetchedObjects objectAtIndex:0]; [currentMessage setUploaded:progress]; [context save:&coreError]; [[NSNotificationCenter defaultCenter] postNotificationName:UPLOAD_UPDATED_NOTIFICATION object:self]; } -
这里我显示消息列表并在表格视图中发送消息:
@implementation TimelineViewController //SOME CODE... - (void)viewWillAppear:(BOOL)animated { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateTable) name:UPLOAD_UPDATED_NOTIFICATION object:nil]; } - (void)updateTable { NSError *error; [[self fetchedResultsController] performFetch:&error]; if ([[_fetchedResultsController sections]count]>0) { [table reloadData]; NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([table numberOfRowsInSection:[[_fetchedResultsController sections]count]-1] - 1) inSection:[[_fetchedResultsController sections]count]-1]; [table scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; } } //SOME CODE... - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { Message *info = [_fetchedResultsController objectAtIndexPath:indexPath]; //MORE CODE... if ([info contentSize]!=NULL) { [cell.progressBar setHidden:NO]; [cell.progressBar setProgress:[[info uploaded]floatValue]]; } } //CODE... - (IBAction)sendMessageAction:(id)sender { CommandServices *services = [[CommandServices alloc]init]; [services sendMessageToGroup:message withMedia:attachedMedia withLocalId:localId]; }
我不知道这是否足以理解我的问题,所以我要问两个主要问题:
- 这是用多个进度条管理多次下载的好方法吗?我的意思是,将进度保存到实体中......或者,我该怎么做?
- 为什么我的应用程序在我上传或下载文件时冻结?也许我对 CoreData 的访问过多?
非常感谢!
【问题讨论】:
-
我认为您在主线程中工作请在后台线程中执行这些任务,这样您的应用在上传和下载时不会冻结
标签: ios objective-c uitableview core-data nsurlconnection