我正在开发一个消息传递客户端(如Whatsapp或Line)。 我遇到了麻烦,因为我需要支持多个下载文件(和上传),在每个有当前下载过程的消息中显示进度条。 多重下载和上传过程已经开发(并且运行正常),当我尝试在消息进度条中显示进度时会出现问题。
我的“解决方案”(我不知道是否有更好的方法)是在CoreData的Message实体中添加“已上传”和其他“已下载”字段,保存上传百分比或下载百分比,并在每次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];
}
我不知道这是否足以理解我的问题,所以我将提出两个主要问题:
非常感谢!
答案 0 :(得分:0)
我的猜测是你应该使用以下代码来获取NSManagedObjectContext:
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [app managedObjectContext];
而不是:
NSManagedObjectContext *context = [[[AppDelegate alloc]init]managedObjectContext];
答案 1 :(得分:0)
嗯......经过几天思考我的问题,我意识到我做了太多的数据库访问,因为我的应用冻结了。 我解决了它传递给我的HTTPConnection对象,我想要管理的进度条的一个实例。并且我只在完成时保存进度下载/上传。
这是我的解决方案:
在HTTPConnection中:
+ (void)setProgressBar:(UIProgressView *)progress
{
[downloadConnection setProgressBar:progress];
}
//CODE...
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
if (self.progressBar) {
self.progressBar.progress = progress;
}
if (progress == 1.0) {
[self saveProgressInDatabase:[NSNumber numberWithFloat:progress]];
}
}
在我的留言列表中:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Message *info = [_fetchedResultsController objectAtIndexPath:indexPath];
//MORE CODE...
if (([info contentSize]!=NULL)&&([[info uploaded]floatValue]<1.0)) {
[HTTPConnection setProgressBar:cell.progressBar];
[cell.progressBar setHidden:NO];
} }
感谢您的帮助!