2014-01-22 70 views
1

我正在开发一个消息客户端(如Whatsapp或Line)。 我在麻烦,因为我需要支持多下载文件(和上传),显示进度条到每个消息有当前的下载过程。 多下载和上传过程已经开发(并且工作正常),当我尝试向消息进度条显示进度时,问题就出现了。多个下载进度条目标c

我的“解决方案” (我不知道是否有更好的方式来做到这一点)是增加一个字段“上传”等“下载”到CoreData消息实体,它保存上传百分比或者下载百分比,并更新该字段每个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]; 
    } 
    

我不知道这是否是不够了解我的问题,所以我我会问两个主要问题:

  1. 这是一个很好的方式来管理与多个进度条的多重下载吗?我的意思是,将进展存入实体......或者,我该怎么做?
  2. 为什么我上传或下载文件时,我的应用程序冻结?也许我对CoreData有太多的访问权限?

非常感谢!

+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]; 
    } } 

感谢您的帮助!

0

我的猜测是,你应该使用下面的代码来获取的NSManagedObjectContext:代替

AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate; 
NSManagedObjectContext *context = [app managedObjectContext]; 

NSManagedObjectContext *context = [[[AppDelegate alloc]init]managedObjectContext]; 
+0

是的,我同意你的意见。这是获得NSManagedObjectContext的更好方法,但这并不能解决我的问题。谢谢你的帮助。 – kemmitorz