2014-01-22 101 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