[iPhone SDK] crash MKMapView / KVO

Aurélien-A

Membre junior
19 Mai 2005
76
3
38
Edinburgh
www.billou-net.info
Hello,

J'ai un petit problème de crash dans le context d'une MKMapView.

Contexte: la mapview est dans un ViewController, lui même dans un NavigationController.

Dans -viewDidLoad j'ai le lignes de code suivantes:

Bloc de code:
(snip)

[_mapView addObserver:self forKeyPath:@"userLocation.location" options:NSKeyValueObservingOptionNew context:NULL];

_mapView.showsUserLocation = YES;

(snip)

Et en tant que handler pour l'observation j'ai ceci:

Bloc de code:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
        {
            (snip)
	}
}

Pour finir j'ai aussi implémenté le code suivant dans -viewDidUnload

Bloc de code:
	_mapView.showsUserLocation = NO;
	[_mapView removeObserver:self forKeyPath:@"userLocation.location"];

Donc a priori je n'ai rien qui manque. Cependant quand je charge la vue (dans le navigation controller) et je clique sur "Back" avant que la première géolocatisation ait eu lieu, j'ai un crash malencontreux:

Bloc de code:
2010-03-29 17:18:46.974 CityQuest[31905:207] ViewDidLoad
2010-03-29 17:18:53.237 CityQuest[31905:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<NSCFType: 0x50115e0>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: userLocation.location
Observed object: <MKMapView: 0x503f530; frame = (0 0; 320 372); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer: 0x503f8d0>>
Change: {
    kind = 1;
    new = <+37.33168900, -122.03073100> +/- 100.00m (speed -1.00 mps / course -1.00) @ 2010-03-29 17:18:53 +0100;
}
Context: 0x0'

Comme si l'observeur n'était jamais déréférencé malgré l'appel à "removeObserver:forKeyPath:" Un moyen de rendre ça un peu plus safe / foolproof? J'ignore totalement si j'ai oublié quelque chose ou si ça doit passer par du foolproofing.

Un bug que j'aurais pas vu?

Merci pour les idées,
Aurélien
 

tatouille

Vétéran
1 Juin 2004
5 174
494
Stanford CA
observing != binding

http://developer.apple.com/mac/libr...CocoaBindings/Concepts/HowDoBindingsWork.html

tu enregistres ton Objet en tant qu' observer (qui devrait etre seulement observable et non observer), DONC ton Objet n'a aucune idée de ce qu'il doit faire quand il reçoit une notification pour une modification SUR LUI-MEME.

donc tu "pourrais" forcer cela en creant une relation sur lui-meme, (et te battre pour eviter une infinite loop)

-bind:toObject:withKeyPath:Options:


mais ce que tu as fait == tout ce qu'il ne faut pas faire, s'observer soi-meme, grosse lacune OOP derriere ton probleme.
 

Aurélien-A

Membre junior
19 Mai 2005
76
3
38
Edinburgh
www.billou-net.info
Merci tatouille pour les conseils, mais je pense que tu n'as pas compris la question. J'ai du mal m'exprimer.

Un objet de type UIViewContoller observe les changements d'une propriété d'un autre objet de type MKMapView. Rien de plus normal. Je ne vois pas où intervient la notion de boucle infinie (ni de l'objet qui reçoit une notification sur lui même).

De plus ma question était sur l'iPhone, pas sur le Mac. Et y'a pas de bindings sur l'iPhone.

Merci pour ton temps quand même, mais j'ai résolu mon problème en travaillant avec dealloc plutôt que -viewDidUnload - dont j'avais mal compris l'usage - et qui n'était pas appelé systématiquement. Mea culpa, c'est ce qui arrive quand on se met pas à jour entre iPhone OS 2 et iPhone OS 3 (viewDidUnload n'existait pas sur le dernier projet que j'ai bossé y'a plus d'un an).