2010-08-18 7 views
0

J'utilise deux threads dans une application iPhone pour la première fois et j'ai rencontré un problème. Dans ce prototype, j'ai un contrôleur de vue qui charge une page web locale. Je veux qu'un indicateur d'activité apparaisse jusqu'à la fin du chargement de la page. Avec le code ci-dessous, l'indicateur d'activité démarre, la page se charge correctement, mais l'indicateur d'activité ne s'arrête pas ou ne se cache pas. Il ne semble pas que la fonction "chargement" soit appelée.Problème NSThread sur iPhone

Qu'est-ce que je fais mal?

- (void)viewDidLoad { 
[self.view addSubview:activityIndicator]; 
[activityIndicator startAnimating]; 
[NSThread detachNewThreadSelector:@selector(getData) toTarget:self withObject:nil]; 
[super viewDidLoad]; 
} 
- (void)getData { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
[detailWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"page1" ofType:@"html"]isDirectory:NO]]]; 
[NSTimer scheduledTimerWithTimeInterval: (1.0/2.0) target:self selector:@selector(loading) userInfo:nil repeats:YES]; 
[pool release]; 
} 
- (void)loading { 
if(!detailWebView.loading){ 
[activityIndicator stopAnimating]; 
[activityIndicator removeFromSuperview]; 
} 
+0

J'apprécie de quelques-unes des réponses que le filetage ne semble pas être nécessaire pour cela, mais je suis en train de comprendre comment utiliser le filetage pour une plus scénario complexe que je vais aborder. Ceci est juste un prototype. –

Répondre

2

Il y a un moyen plus facile de le faire sans créer votre propre fil.

- (void)viewDidLoad { 
    [self.view addSubview:activityIndicator]; 
    [activityIndicator startAnimating]; 
    [detailWebView setDelegate:self]; 
    [detailWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"page1" ofType:@"html"]isDirectory:NO]]]; 
    [super viewDidLoad]; 
} 

- (void)webViewDidFinishLoad:(UIWebView *)webView { 
    [activityIndicator stopAnimating]; 
} 
1

Vous d betetr arrêter l'indicateur d'activité dans la méthode déléguée WebView:

-(void)webViewDidFinishLoad:(UIWebView*)webView 
+0

Oui ... en fait, je pense qu'il n'y a pas besoin de filetage ici du tout. – DarkDust

+0

C'était mon prototype simple. Dans la version complète, je vais analyser un grand fichier XML, donc j'ai pensé que je ferais mieux de comprendre comment exécuter plusieurs threads. –

0

Avez-vous ajouté à la sortie de débogage loading si elle est appelée? Le code ressemble à ça, il devrait être appelé après 0.5 secondes et je suppose que detailWebView est encore en train de charger.

En outre, des trucs de GUI doit être exécuté sur le thread principal, vous devrez peut-être faire:

- (void)loading { 
    if(!detailWebView.loading){ 
    [activityIndicator performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:YES]; 
    [activityIndicator performSelectorOnMainThread:@selector(removeFromSuperView) withObject:nil waitUntilDone:YES]; 
    } 
} 
+0

Je pense que c'est probablement la solution au problème. Je suppose que je ne m'assurais pas que les actions étaient sur le fil principal. J'ai essayé ce code mais l'application s'est écrasée. Si je viens d'utiliser la ligne "stopAnimating", cela l'a arrêté. Je suppose qu'il y a un problème avec la commande removeFromSuperView que je dois regarder. –

+0

OK Peut-être que j'étais un peu prématuré dans mon dernier commentaire. Ca fonctionnait parce que j'avais commenté du code (doh!). J'ai ajouté du code de débogage et je peux maintenant voir que la fonction de chargement n'est jamais appelée. Est-il toujours possible d'utiliser une cible de self dans NSTimer dans cette situation de thread multiple? –

+0

Je vous suggère d'éviter les threads tout à fait pour cela et faites-le comme suggéré par Kubi, c'est vraiment la bonne solution et ne créera pas de maux de tête. – DarkDust

0

Vous utilisez un WebView, qui fournit déjà un mécanisme permettant de savoir quand une charge est terminée, et charge déjà des données de manière asynchrone - l'utilisation d'un fil personnalisé est vraiment pas nécessaire.

Enregistrez votre objet en tant que délégué de UIWebView. Appelez loadRequest sur l'UIWebView et commencez à animer l'indicateur de progression. Arrêtez animant l'indicateur de progression dans:

-(void)webViewDidFinishLoad:(UIWebView*)webView 

Cette méthode est définie par le protocole UIWebViewDelegate - assurez-vous que votre objet implémente ce protocole. Vous mettez en oeuvre cette méthode:

- (void)webViewDidFinishLoad:(UIWebView *)webView { 
    [activityIndicator stopAnimating]; 
} 

http://developer.apple.com/iphone/library/documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html