2008-11-23 6 views
24

J'essaye d'intégrer un objet NSURLConnection avec UIProgressView, ainsi je peux mettre à jour l'utilisateur pendant qu'un téléchargement de fichier se produit en arrière-plan.Comment intégrer NSURLConnection avec UIProgressView?

J'ai créé un objet séparé pour télécharger le fichier en arrière-plan, et je n'arrive pas à trouver comment mettre à jour la propriété progress dans l'objet UIProgressView avec la valeur correcte. C'est probablement quelque chose de très simple, mais je n'arrive pas à me débrouiller avec Googling.

Voici le code que j'ai:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    [self.resourceData setLength:0]; 
    self.filesize = [NSNumber numberWithLongLong:[response expectedContentLength]]; 
    NSLog(@"content-length: %d bytes", self.filesize); 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [self.resourceData appendData:data]; 

    NSNumber *resourceLength = [NSNumber numberWithUnsignedInteger:[self.resourceData length]]; 
    NSLog(@"resourceData length: %d", [resourceLength intValue]); 
    NSLog(@"filesize: %d", self.filesize); 
    NSLog(@"float filesize: %f", [self.filesize floatValue]); 
    progressView.progress = [resourceLength floatValue]/[self.filesize floatValue]; 
    NSLog(@"progress: %f", [resourceLength floatValue]/[self.filesize floatValue]); 
} 

Comme vous pouvez le voir, la variable membre resourceData contient les données de fichier tel qu'il est en cours de téléchargement. La variable de membre taille de fichier contient la taille complète du fichier, tel que renvoyé par mon service Web dans son en-tête Content-Length. Tout fonctionne en quelque sorte OK, je continue à obtenir les données téléchargées avec plusieurs exécutions de didReceiveData comme je devrais, mais quand j'essaie de calculer la valeur de progression, aucune valeur correcte n'est retournée. Voir ci-dessous pour un petit échantillon de ce que je reçois dans mon journal de la console:

content-length: 4687472 bytes 
resourceData length: 2904616 
filesize: 4687472 
float filesize: -1.000000 
progress: -2904616.000000 

Pour référence, progressView.progress est un flotteur. taille de fichier est un NSNumber qui tient longtemps. Enfin, resourceLength est un NSNumber qui contient un NSUInteger.

Qu'est-ce qui me manque ici?

+0

Qu'est-ce qui est enregistré sur la console lorsque vous exécutez cette opération? Les champs de progression sont-ils correctement imprimés? –

+0

Ben, vient d'ajouter un échantillon du journal de la console. – jpm

Répondre

29

Je ne sais pas ce qui me manque ici, mais votre filesize étant -1 semble être votre problème. Le API docs indique clairement que expectedContentLength peut ne pas être disponible et que NSURLResponseUnknownLength est renvoyé dans ces cas. NSURLResponseUnknownLength est défini comme:

#define NSURLResponseUnknownLength ((long long)-1) 

Dans ce cas, vous ne pouvez pas obtenir un progrès précis. Vous devrez gérer cela et afficher un indicateur de progression indéterminé.

+0

Dave, merci pour la réponse. J'ai ajouté un appel supplémentaire NSLog() pour illustrer mon point de vue. J'ai ajouté une déclaration de débogage enregistrant "contenu-longueur" ci-dessus. – jpm

+0

Je suppose que je ne comprends pas la question, alors ... qu'est-ce que vous demandez exactement? –

+0

Je demande: qu'est-ce qui me manque? Pourquoi [self.filesize floatValue] renvoie -1 au lieu de la valeur float réelle de son objet NSNumber (qui représente un long long)? Pourquoi le calcul de division est-il complètement cassé comme ça? – jpm

6

Je pense que vous imprimez la mauvaise taille de fichier. Si self.filesize est en effet un NSNumber, vous l'imprimer en utilisant le format %@, car il est un objet, pas une primitive:

NSLog(@"filesize: %@", self.filesize); 

En utilisant le %d, votre imprimez simplement le pointeur valeur de self.filesize . Pour imprimer la valeur à long temps réel, utilisez %lli (%d est uniquement pour les valeurs 32 bits):

NSLog(@"filesize: %lli", [self.filesize longLongValue]); 

Ainsi, votre self.filesize est en fait -1 et la division est correcte.

+0

Dave, assez juste sur l'erreur NSLog(). Cependant, ce que je veux vraiment faire est de calculer une valeur flottante (à partir de 2 objets NSNumber) à assigner à progressView.progress. Comme vous pouvez le voir ci-dessus, je n'obtiens pas la valeur attendue en faisant une simple division. – jpm

+1

Vous le faites très bien! 2904616/-1 = -2904616 –

+1

Plus spécifiquement 2904616/NSURLResponseUnknownLength = -2904616 –

0

Dans votre code, la taille de fichier semble être un objet NSNumber (!).Alors

NSLog(@"filesize: %d", self.filesize);

et

NSLog(@"content-length: %d bytes", self.filesize);

rapportera probablement quelque chose comme l'adresse (id) de cet objet (ou autre chose). Ceci est le

filesize: 4687472

vous voyez. Comme l'a souligné par d'autres, la taille du fichier retourné par la réponse est en effet -1, à savoir,

NSURLResponseUnknownLength

à savoir, le serveur n'a retourné la taille du fichier.