La façon correcte de le déclarer, alloc, de charge et de dealloc un NSMutableArray
Je déclare mon tableau dans mon *.h fichier:
@interface aViewController: UIViewController { NSMutableArray *anArray; //Vous aurez besoin pour modifier ultérieurement à de nombreuses reprises. } @end
J'alloue de la mémoire pour mon *.m fichier:
-(void) viewDidLoad { anArray = [[NSMutableArray alloc] init]; }
Je clique sur un test-bouton pour charger mon tableau (finalement, il aura besoin de charger DIFFÉRENTES valeurs
sur chaque clic):
anArray = [NSMutableArray arrayWithObjects:@"un", @"deux", @"trois", nil];
Et je gratuit ici:
-(void) dealloc { [anArray release]; [super dealloc]; }
Fait que tous l'air ok?
Car il se bloque quand je plus tard l'exécution de ce code:
NSLog(@"%d", [anArray count]);
Pas pourquoi un simple "NSLog() et count" crash tout.
Dirk,
Permettez-moi de le dire de cette manière: j'ai un ÉNORME incompréhension de pointeurs, tableaux, chaînes de caractères, et de la mémoire.
J'ai lu tout ce que je peux trouver à ce sujet... mais (encore) de trouver une forme simple, claire, facile-à-comprendre la description.
Peut vous en proposer un? (J'espère moins de 10 pages de lecture.)
Est-il une référence qui explique JUSTE ce sujet... et à partir d'un point de vue ", vous disposez de 12 ans d'expérience du développement... mais AUCUN qui ait jamais traité avec de l'allocation de mémoire ou des pointeurs".)
Donc la variable nom est PAS la façon dont je me réfère à l'objet?
Alors pourquoi l'avoir?
Je suis utilisé pour de nombreuses autres langues viens de le faire:
myString = "ce" myString = "que" myInt = 5 myInt = 15
(Ce qui pourrait être plus simple.)
Me semble que ce serait la meilleure façon de le faire.
(Et il semble fonctionner. Mais c'est vraiment correct?)
N'avez pas d'allocation de la mémoire pour mon NSMutableArray initialement. Ne pas ré-allocation de la mémoire à plusieurs reprises. (Quand j'ai changer mon tableau de valeurs). Ne relâchez pas à plusieurs reprises. (Avant de me changer mon tableau de valeurs). Ne relâchez pas quand je l'ai quitter le programme. Mais: Rappelez-vous de toujours utiliser RETENIR quand j'ai d'abord attribuer (et à plusieurs reprises réaffecter), de nouvelles valeurs pour mon anArray variable.
Vous n'êtes pas le chargement de votre tableau avec
anArray = [NSMutableArray arrayWithObjects:@"un", @"deux", @"trois", nil];
Au lieu de cela, vous la remplacez par une nouvelle instance, et pour le pire: avec un exemple, dont l'
de référence est détenue par une autre entité que vous n'avez pas de contrôle
Wow. Si je pouvais avoir 20 tableaux... tous appelés du même nom: anArray... et ils seraient tous différents? (Il n'y a pas une telle chose comme un tableau GLOBAL?)
etc. Afin d'effacer les anciennes valeurs, la méthode removeAllObject peut être à portée de main.
Il y a aussi la mutation des méthodes, qui peut être utilisé pour ajouter plusieurs valeurs à la fois.
Donc... je dois d'abord supprimer tous les objets"... et puis je peux appeler UN méthode de re-ajouter toutes mes nouvelles valeurs.
anArray = [[NSMutableArray arrayWithObjects:@"un", @"deux", @"trois", nil] retain];
au lieu de l'allocation/init séquence.
Wow. Je pensais que rien ne pouvait être stockées dans un tableau sans alloc avec de l'espace pour cela.
Si vous avez vraiment l'intention de remplacer l'ensemble de la matrice, vous pouvez envisager de
en utilisant les propriétés
Comment pourrais-je le faire à l'aide de propriétés?
Quelle serait la bonne façon de faire quelque chose comme ceci:
> anArray = [NSMutableArray arrayWithObjects:@"un", @"deux", @"trois", nil]; > anArray = [NSMutableArray arrayWithObjects:@"quatre", @"cinq", @"six", nil];
Tout comme je le ferais:
x = 12; x = 24;
Wow. Je VRAIMENT ont totalement méconnaître tout à propos de chaînes, de tableaux, et de la mémoire.
Je pensais que la "voie facile" était d'alloc une FOIS... la mutable tableau... le modifier autant que vous voulez... et de les libérer une FOIS.
Le problème avec cela est que ce tableau n'est pas conservé,
Je pense que les vieux de la matrice serait parti... et le nouveau tableau pourrait être utilisé.
(Mais je ne pense pas.)
En outre, vous avez une fuite de mémoire parce que vous n'avez jamais libéré le tableau d'origine.
Je pensais l'ancien tableau n'est pas supposé être libéré... je ne suis pas fini avec elle... je souhaite juste CHANGER pour contenir mes nouvelles valeurs. (Mais je ne pense pas.)
mais on est à utiliser [anArray release];
Je pensais qui me ferait libérer la mémoire que j'ai alloué... (mais je ne crois pas)... et puis je dois ré-allocation de la mémoire. (Mais je ne pense pas.)
anArray = [[NSMutableArray arrayWithObjects:@"un", @"deux", @"trois", nil] retain];
J'ai donc à "conserver"... donc il ne disparaîtra pas de sous moi?
(Je ne sais pas pourquoi il le ferait. Jusqu'à ce que je le dire... dans mon dernier dealloc appel.)
Un autre, probablement plus correct moyen pour résoudre ce problème serait d'utiliser la addObject: ou
addObjectsFromArray: NSMutableArray méthodes au lieu de constamment créer de nouveaux tableaux.
Je ne veux créer UN tableau... et il suffit de l'utiliser comme je veux.
Je ne veux plus jamais AJOUTER à la matrice. Je veux mettre mes nouvelles valeurs.
- Je sais que ce post est vieux âges à l'heure d'internet, mais je tiens à préciser que dans le développement du Cacao, nous sommes tout simplement JAMAIS vraiment la manipulation de structures de données eux-mêmes, mais plutôt des pointeurs vers eux. Gardez cela à l'esprit en tout temps et gardez à l'esprit que vous devez être très prudent avec le pointeur de la cession.
- Je souhaite que je pourrais vous donner plus d'un vote - j'ai exactement les mêmes problèmes - Objectif C est au-delà de contre-intuitifs.
Vous devez vous connecter pour publier un commentaire.
Vous n'êtes pas le chargement de votre tableau avec
Au lieu de cela, vous la remplacez par une nouvelle instance, et pire encore: avec une instance, dont la référence est en fait possédé par une entité vous n'avez pas le contrôle (le plus probablement, une
NSAutoreleasePool
.) La référence bien vous appartenant, l'un créé parest perdu et sera coulé.
Au lieu de remplacer l'ensemble de la matrice de référence, la mutation de l'un, vous avez à votre disposition déjà, en utilisant par exemple
addObject:
commeetc. Afin d'effacer les anciennes valeurs, la méthode
removeAllObject
peut être à portée de main. Il y a aussi la mutation des méthodes, qui peut être utilisé pour ajouter plusieurs valeurs à la fois.Alternativement, vous pouvez allouer le tableau à l'aide de la méthode de construction que vous utilisez déjà, mais attention à la conserver. Dans
viewDidLoad
neau lieu de la
alloc
/init
séquence.Si vous avez vraiment l'intention de remplacer l'ensemble de la matrice, vous pouvez envisager d'utiliser propriétés au lieu de faire le comptage de référence manuellement.
Le problème est
anArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
Cela remplace la matrice que vous avez initialement créé. Le problème avec cela est que ce tableau n'est pas conservé, de sorte que vous perdre dès le retour de la méthode. En outre, vous avez une fuite de mémoire parce que vous n'avez jamais libéré le tableau d'origine.Il existe plusieurs façons de résoudre ce problème, mais l'une est d'utiliser
[anArray release]; anArray = [[NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil] retain];
à la place.Un autre, probablement plus correct moyen pour résoudre ce problème serait d'utiliser la
addObject:
ouaddObjectsFromArray:
NSMutableArray
méthodes au lieu de constamment créer de nouveaux tableaux.Rappelez-vous cette simple mémoire règle: seulement libérer des objets que vous possédez. Vous possédez des objets uniquement lorsque vous les créez à l'aide de:
init
(cette méthode crée un nouvel objet à conserver un nombre de 1)new
(cette méthode est la même que l'utilisation d'allocation et initialisation)copy
(cette méthode crée un nouvel objet à conserver un nombre de 1 et avec le contenu du récepteur de la méthode)retain
(cette méthode augmente les conserver compter 1)Le système
dealloc
ates automatiquement les objets à conserver un nombre de zéro. Vous devezrelease
chaque objet vous-même après que vous avez terminé avec elle. Si vousrelease
trop tôt, vous obtenez une situation dangereuse. Si vous n'avez pasrelease
votre objet lorsque vous avez terminé avec cela, vous obtenez une fuite.Un pointeur est un objet spécial qui se réfère à un objet en mémoire. En gros, c'est une adresse en mémoire (et d'autres données). Si vous voulez utiliser un objet, vous devez
alloc
mangé de mémoire pour elle et puisinit
ialize. Vous affectez (à l'aide de la=
signe) à un pointeur.string
a maintenant conserver un nombre d'une. Mais parce queNSString
est immuable de l'objet, il ne peut pas être modifié après l'initialisation. Une façon d'attribuerstring
une valeur est de le faire lors de l'initialisation d'elle.Si vous avez besoin de changer
string
régulièrement, vous pouvez utiliser une autre classe qui est mutable:NSMutableString
. Mais encore, la seule façon de changer les choses est dans un message.Juste pour remarque, le code suivant est mal et entraîne une fuite de mémoire.
Dans la première ligne,
string
est affecté à un objet nouvellement créé. Dans la seconde,string
est affecté à une autre chaîne. Vous perdez la référence à l'objet nouvellement créé, et vous obtenez une fuite: vous ne pouvez pas libérer un objet que vous n'avez pas de référence à l'.Vous n'obtenez pas un problème lorsque vous effectuez cette opération avec des nombres entiers (
int
type), parce que c'est un "natif" de l'objet. L'Objective-C Runtime associe ces types de données directement auprès de leur valeur, et non pas un pointeur.Note 1. N'oubliez pas de dire à l'exécution de ce type de votre pointeur. Si vous souhaitez utiliser
string
, il faut le définir en premier dans votre en-tête (si elle est publique) ou la mise en œuvre (si vous voulez qu'il soit caché à d'autres méthodes). Ensuite, vous pouvez utiliser le nom librement.L'étoile indique à l'exécution, il est un pointeur. Pour les types natifs, il n'y pas de pointeur, de sorte que vous obtenez ce.
Note 2. Les tableaux (et les dictionnaires, etc.) se comportent tous comme des
NSString
en ce qu'ils ont à la fois immuable et changeante des variantes.Note 3. La plupart des classes ont des méthodes spéciales qui allouer, d'initialisation et de autorelease tout à la fois.
Un autoreleased objet n'a pas besoin de manuel
release
que le systèmerelease
pour vous après un certain temps. C'est très pratique dans les situations où vous avez besoin d'un objet uniquement pour la durée de la méthode ou entre les méthodes, non pas comme une partie intégrante d'un objet. Lorsque vousautorelease
un objet sur le thread principal (dans une application avec une interface graphique), il serarelease
d lorsque la boucle se termine la boucle de courant (il se termine lorsqu'un événement est traité). Lire plus à propos de Autorelease Piscines d'Apple docs.J'espère que j'aide tout le monde qui ne comprennent pas bien ce que les pointeurs sont. J'ai moi-même eu des problèmes pendant quelques mois jusqu'à ce que j'ai expérimenté beaucoup. 🙂
release
tout à fait. 😉