Crash sur variable statique
J'obtiens un crash (aléatoire) sur un retour du mode Background sur le morceau de code ci-dessous:
+ (NSString *) NLSystemUserAgent {
static NSString *_userAgent;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
UIWebView *webView = [[[UIWebView alloc] initWithFrame:CGRectZero] autorelease];
_userAgent = [webView stringByEvaluatingJavaScriptFromString:@navigator.userAgent];
});
return _userAgent;
}
J'ai un bad_access sur _userAgent.
Une idée?
Pour info je n'utilise pas ARC.
Voici la solution que je propose (pas glop):
+ (NSString *)NLSystemUserAgent {
static NSString *_userAgent;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
_userAgent = [[webView stringByEvaluatingJavaScriptFromString:@navigator.userAgent] retain];
[webView release];
});
if (_userAgent)
[[NLUserDefault standardUserDefaults] setObject:_userAgent forKey:@NL_UserAgent];
else {
NSString* userAgent = [[NLUserDefault standardUserDefaults] objectForKey:@NL_UserAgent];
if (userAgent)
_userAgent = userAgent;
else _userAgent = @Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Mobile/11D257 ;
//Pas Glop, mais ça ne devrait pas arriver...
}
return _userAgent;
}
Merci d'avance.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Après je sais pas si c'est la cause de ton EXC_BADACCESS, mais bon ça pourrait être une bonne idée de protéger tout cela comme il faut quand même.
2) En plus, utiliser une UIWebView (donc composant d'UI) juste pour récupérer le User-Agent (= info métier) je suis pas sûr que ce soit la meilleure des solutions (même si c'est celle qu'on trouve le + sur Google, ça veut pas dire que c'est la meilleure, on trouve bien quelques autres aberrations sur Google concernant certaines pratiques iOS...), je serais toi je chercherai un moyen plus propre s'il en existe
Tu penses que ça pourrait résoudre le problème?
- la logique avec les UserDefaults est bizarre (puisque tu ne vas chercher l'info dedans QUE si ton userAgent n'a pas (encore) été initialisé, au lieu qu'ils overrident la valeur comme c'est sensé être le cas d'usage classique
- pourquoi un dispatch_async, rendant ainsi ta méthode asynchrone alors qu'elle continue de retourner la valeur de manière synchrone ?
Si je peux te demander, pourquoi éviter l'ARC ?
C'est historique dans ce projet ^^
T'as raison pour le userDefault. J'me suis embrouillé entre temps.
Le dispatch_async, c'est pour chopper la mainQueue. Lors du premier appel la valeur peut etre différente, mais ensuite ça corrige. En soit ça n'est pas très grave.
Pourquoi ne pas rester en synchrone ? Faut juste faire attention si tu es déjà sur le mainThread, à ne pas faire un dispatch_sync sur lui-même, car dans ce cas tu aurais un DeadLock. Mais sinon, c'est inutile et pas logique de passer en asynchrone... surtout si tu continues de retourner une valeur avec un "return" à la fin !
Merci Ali.
Je ne savais pas qu'on pouvait faire comme ça.