Comment remplacer les références faibles lors de l'utilisation d'ARC et du ciblage d'iOS 4.0?

87

J'ai commencé à développer ma première application iOS avec Xcode 4.2 et ciblais iOS 5.0 avec un modèle "d'application utilitaire" (celui qui est fourni avec un FlipsideViewController).

J'ai lu que, puisque ARC est une fonctionnalité de compilation, il devrait également être compatible avec iOS 4, j'ai donc tenté de cibler mon application sur 4.3 et d'essayer de la compiler. Lorsque je le fais, j'obtiens cette erreur:

FlipsideViewController.m: erreur: comptage automatique des références Problème: la cible de déploiement actuelle ne prend pas en charge les références __weak automatisées

Il fait référence à cette ligne:

@synthesize delegate = _delegate;

Cette variable est déclarée comme:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

Je comprends que les «références faibles» ne sont pas prises en charge dans iOS 4, mais je ne comprends pas vraiment pourquoi je voudrais utiliser une référence faible pour commencer, et je ne peux pas non plus comprendre comment réécrire les choses pour éviter de l'utiliser, alors que profitant toujours d'ARC (après tout, il est censé fonctionner avec iOS 4 ET 5, n'est-ce pas?)

Mason G. Zhwiti
la source

Réponses:

149

Pour cibler l'ancien système d'exploitation, vous pouvez utiliser unsafe_unretainedau lieu de weakdans votre déclaration de propriété, et cela devrait principalement fonctionner de la même manière. weakréférences nulles elles-mêmes lorsque leur cible disparaît, mais unsafe_unretainedlaisse ouverte la possibilité que l'objet auquel vous liez puisse se transformer en un pointeur suspendu lorsqu'il est désalloué. Ce dernier est le même comportement que si vous l'aviez utilisé assigncomme déclaration de propriété dans la gestion manuelle de la mémoire.

Vous faites cela pour éviter de retenir les cycles, que je mentionne dans ma réponse ici . Vous ne voulez pas avoir un pointeur fort vers quelque chose qui pourrait avoir un pointeur fort vers l'objet d'origine. Alors rien ne serait libéré correctement.

Brad Larson
la source
Merci pour le conseil. Vous dites "pour cibler l'ancien système d'exploitation ...". Cela signifie-t-il que je ne devrais utiliser unsafe_unretained que dans les versions de l'application antérieures à 5.0? Ou puis-je simplement utiliser unsafe_unretained dans mon code et le construire pour cibler à la fois 4.x et 5.x?
Mason G. Zhwiti
1
@Mason - unsafe_unretainedest pris en charge dans iOS 4.x et 5.0, il vous offre donc une compatibilité ascendante. Si vous faisiez une version 5.0 uniquement, vous pouvez passer à weakpour profiter de la sécurité supplémentaire qu'elle vous offre.
Brad Larson
J'ai essayé unsafe_unretained, cela a fonctionné de toute façon. Cependant, j'ai reçu beaucoup d'avertissements comme '"** __NSAutoreleaseNoPool (): Objet 0x564bd90 de classe __NSArrayM autoreleased sans pool en place - juste une fuite" *', c'est normal?
cinquième
1
@fifth - C'est un problème totalement indépendant. Vous exécutez quelque chose sur un thread d'arrière-plan sans disposer d'un pool de libération automatique. Les threads créés manuellement n'ont pas leur propre pool de libération automatique, vous devez donc en créer un vous-même en utilisant @autoreleasepool(sous ARC, NSAutoreleasePool pour les implémentations plus anciennes comptées manuellement).
Brad Larson
@Brad, c'est utile, les avertissements sont partis, j'ai reçu plusieurs appels à performSelectorInBackground.
cinquième
11

Si vous n'utilisez que des références faibles pour plus de sécurité, appelez manuellement les nouvelles fonctions d'exécution si elles sont disponibles et revenez à l'affectation simple sur les __unsafe_unretainedvariables si ce n'est pas le cas.

ZWRCompatibility.h simplifiera quelque peu cela.

rpetrich
la source
10

Grâce à la bibliothèque de compatibilité PLWeakCompatibilty de Mike Ash , vous pouvez maintenant simplement utiliser __weak sur iOS 4.x, ainsi.

Il est incroyablement facile à configurer et ne nécessite aucune considération ou effort supplémentaire par rapport à 5.x.

nschum
la source