béryllium: tout à fait raison. vladof81: Bien sûr que non.
gnasher729
Réponses:
511
NSArray*array=[mutableArray copy];
Copyfait des copies immuables. C'est très utile car Apple peut effectuer diverses optimisations. Par exemple, l'envoi copyà un tableau immuable ne conserve que l'objet et retourne self.
Si vous n'utilisez pas le ramasse-miettes ou ARC, n'oubliez pas que -copyconserve l'objet.
cette réponse est excellente, mais comment savoir à partir des documents qui copycréent un NSArray normal et non un NSMutableArray?
Dan Rosenstark
22
@Yar: Vous regardez la documentation de NSCopying Il y est indiqué : copyWithZone La copie retournée est immuable si la considération «immuable vs mutable» s'applique à l'objet récepteur; sinon, la nature exacte de la copie est déterminée par la classe.
Georg Schölly
1
Très soigné - je préfère cela à la solution de m5h. À la fois concis et plus efficace.
David Snabel-Caunt
1
Je suis d'accord David, a mis à jour ma réponse pour pointer vers cette réponse.
hallski
2
@Brad: Cela signifie simplement des classes qui ont à la fois des implémentations mutables et immuables. Par exemple NSArray& NSMutableArray, NSString& NSMutableString. Mais pas par exemple NSViewControllerqui contient toujours un état mutable.
Georg Schölly
361
An NSMutableArrayest une sous-classe de NSArraydonc vous n'aurez pas toujours besoin de convertir, mais si vous voulez vous assurer que le tableau ne peut pas être modifié, vous pouvez créer l'une NSArrayou l'autre de ces façons selon que vous souhaitez qu'il soit libéré automatiquement ou non:
/* Not autoreleased */NSArray*array=[[NSArray alloc] initWithArray:mutableArray];/* Autoreleased array */NSArray*array=[NSArray arrayWithArray:mutableArray];
EDIT: La solution fournie par Georg Schölly est une meilleure façon de le faire et beaucoup plus propre, surtout maintenant que nous avons ARC et que nous n'avons même plus besoin d'appeler la libération automatique.
Puis-je simplement faire (NSArray *) myMutableArray?
Vojto
2
Oui, car NSMutableArray est une sous-classe de NSArray qui est valide.
hallski
4
Cependant, la conversion vers (NSArray *) permet toujours une conversion vers (NSMutable *). N'est-ce pas le cas?
sharvey
1
@sharvey: Oui, c'est exact. Vous obtiendrez un avertissement si vous ne lancez pas mais assignez directement une superclasse à une sous-classe. Habituellement, vous souhaitez renvoyer une copie immuable, car c'est la seule façon d'être sûr que votre tableau ne sera vraiment pas modifié.
Georg Schölly
1
Anciennement connu sous le nom de "Upcasting" (NSArray *) myMutableArray et l'inverse est appelé "Downcasting"
C'est tellement faux. Je viens de vérifier. [copie mutableArray] renvoie également un tableau vide.
durazno
@durazno Ce n'est pas faux. Vérifiez votre test. Si [copie mutableArray] renvoie un tableau vide, alors mutableArray doit être un tableau vide. Ma réponse ne s'applique que lorsque mutableArray est nul.
Richard Venable
Bien que cela soit vrai, j'ai l'impression que vous manquez une vérité plus fondamentale dans votre exemple. Puisque vous avez affecté mutableArray à nil, [mutableArray copy]peut être simplifié en [nil copy]. Dans objective-c, tout message envoyé à nil sera toujours nul. Il est important de se rappeler la distinction entre "rien" et "un tableau sans rien".
mkirk
@mkirk Ne nous distrayons pas de la question posée: "Comment convertir NSMutableArray en NSArray?" Il existe 2 solutions principales, et la principale différence entre elles est la manière dont elles se comportent lorsque le tableau mutable est nul.
Qu'est-ce que cela fait que les autres ne font pas?
Ben Leggiero
5
Objectif c
Vous trouverez ci-dessous un moyen de convertir NSMutableArray en NSArray:
//oldArray is having NSMutableArray data-type.//Using Init with Array method.NSArray*newArray1 =[[NSArray alloc]initWithArray:oldArray];//Make copy of arrayNSArray*newArray2 =[oldArray copy];//Make mutablecopy of arrayNSArray*newArray3 =[oldArray mutableCopy];//Directly stored NSMutableArray to NSArray.NSArray*newArray4 = oldArray;
Rapide
Dans Swift 3.0, il existe un nouveau type de données Array . Déclarez Array en utilisant un letmot-clé, il deviendrait NSArray. Et si vous déclarez en utilisant un varmot-clé, il deviendrait NSMutableArray .
La partie Swift n'est pas tout à fait raison. Voir ici et ici pour la différence entre les Arrays et NSArray/ NSMutableArrays mutables / immuables . Ils ne sont pas les mêmes.
Cet [mutableArray copy]antipattern est partout dans l'exemple de code. Arrêtez de le faire pour les tableaux mutables jetables qui sont transitoires et qui sont désalloués à la fin de la portée actuelle.
Il n'y a aucun moyen que le runtime optimise la copie inutile d'un tableau mutable qui est sur le point de sortir de la portée, décréfé à 0 et désalloué pour de bon.
Assigner un NSMutableArrayà une NSArrayvariable ne le convertira pas (c'est la question du PO). L'exposition d'une telle valeur (par exemple en tant que valeur de retour ou en tant que propriété) pourrait entraîner des problèmes de débogage très difficiles si cette valeur était modifiée de manière inattendue. Cela s'applique aux mutations internes et externes, car la valeur mutable est partagée.
David Rönnqvist
Pour muter ce tableau, vous devez [NSMutableArray arrayWithArray: ... ou quelque chose comme ça.
Anton Tropashko
Pas nécessairement. Il suffit de l'assigner à une NSMutableArrayvariable. Étant donné que l'objet n'a jamais cessé d'être un tableau mutable, l'appel de méthodes de mutation réussira et mutera les données partagées. Si, d'autre part, le tableau mutable d'origine était copié - en le changeant en un tableau immuable - puis assigné à une NSMutableArrayvariable et que des méthodes de mutation y étaient appelées, ces appels échoueraient avec des doesNotRespondToSelectorerreurs car l'objet qui a reçu l'appel de méthode de mutation est dans fait immuable et ne répond pas à ces méthodes.
David Rönnqvist
ok, cela pourrait avoir un certain mérite pour les développeurs qui ne tiennent pas compte de l'avertissement du compilateur sur les affectations de conversion de tyope
Anton Tropashko
1
Si vous construisez un tableau via la mutabilité et que vous souhaitez ensuite retourner une version immuable, vous pouvez simplement retourner le tableau mutable en tant que "NSArray" via l'héritage.
Si vous "faites confiance" à l'appelant pour traiter l'objet de retour (techniquement encore modifiable) comme un NSArray immuable, c'est une option moins coûteuse que [mutableArray copy].
Pour déterminer s'il peut modifier un objet reçu, le destinataire d'un message doit s'appuyer sur le type formel de la valeur de retour. S'il reçoit, par exemple, un objet tableau typé immuable, il ne doit pas tenter de le muter . Ce n'est pas une pratique de programmation acceptable de déterminer si un objet est modifiable en fonction de son appartenance à la classe.
La pratique ci-dessus est discutée plus en détail ici:
je cherchais la réponse dans swift 3 et cette question a été montrée comme premier résultat dans la recherche et je suis inspiré de la réponse alors voici le code swift 3
let array:[String]= nsMutableArrayObject.copy() as![String]
NSArray *array = [mutableArray copy];
NSArray *array = mutableArray;
Réponses:
Copy
fait des copies immuables. C'est très utile car Apple peut effectuer diverses optimisations. Par exemple, l'envoicopy
à un tableau immuable ne conserve que l'objet et retourneself
.Si vous n'utilisez pas le ramasse-miettes ou ARC, n'oubliez pas que
-copy
conserve l'objet.la source
copy
créent un NSArray normal et non un NSMutableArray?NSArray
&NSMutableArray
,NSString
&NSMutableString
. Mais pas par exempleNSViewController
qui contient toujours un état mutable.An
NSMutableArray
est une sous-classe deNSArray
donc vous n'aurez pas toujours besoin de convertir, mais si vous voulez vous assurer que le tableau ne peut pas être modifié, vous pouvez créer l'uneNSArray
ou l'autre de ces façons selon que vous souhaitez qu'il soit libéré automatiquement ou non:EDIT: La solution fournie par Georg Schölly est une meilleure façon de le faire et beaucoup plus propre, surtout maintenant que nous avons ARC et que nous n'avons même plus besoin d'appeler la libération automatique.
la source
J'aime les deux solutions principales:
Ou
La principale différence que je vois en eux est la façon dont ils se comportent lorsque mutableArray est nul :
la source
[mutableArray copy]
peut être simplifié en[nil copy]
. Dans objective-c, tout message envoyé à nil sera toujours nul. Il est important de se rappeler la distinction entre "rien" et "un tableau sans rien".vous essayez ce code ---
et
la source
Objectif c
Vous trouverez ci-dessous un moyen de convertir NSMutableArray en NSArray:
Rapide
Dans Swift 3.0, il existe un nouveau type de données Array . Déclarez Array en utilisant un
let
mot-clé, il deviendrait NSArray. Et si vous déclarez en utilisant unvar
mot-clé, il deviendrait NSMutableArray .Exemple de code:
la source
Array
s etNSArray
/NSMutableArray
s mutables / immuables . Ils ne sont pas les mêmes.Dans l'objectif-c:
En bref:
la source
Cet
[mutableArray copy]
antipattern est partout dans l'exemple de code. Arrêtez de le faire pour les tableaux mutables jetables qui sont transitoires et qui sont désalloués à la fin de la portée actuelle.Il n'y a aucun moyen que le runtime optimise la copie inutile d'un tableau mutable qui est sur le point de sortir de la portée, décréfé à 0 et désalloué pour de bon.
la source
NSMutableArray
à uneNSArray
variable ne le convertira pas (c'est la question du PO). L'exposition d'une telle valeur (par exemple en tant que valeur de retour ou en tant que propriété) pourrait entraîner des problèmes de débogage très difficiles si cette valeur était modifiée de manière inattendue. Cela s'applique aux mutations internes et externes, car la valeur mutable est partagée.NSMutableArray
variable. Étant donné que l'objet n'a jamais cessé d'être un tableau mutable, l'appel de méthodes de mutation réussira et mutera les données partagées. Si, d'autre part, le tableau mutable d'origine était copié - en le changeant en un tableau immuable - puis assigné à uneNSMutableArray
variable et que des méthodes de mutation y étaient appelées, ces appels échoueraient avec desdoesNotRespondToSelector
erreurs car l'objet qui a reçu l'appel de méthode de mutation est dans fait immuable et ne répond pas à ces méthodes.Si vous construisez un tableau via la mutabilité et que vous souhaitez ensuite retourner une version immuable, vous pouvez simplement retourner le tableau mutable en tant que "NSArray" via l'héritage.
Si vous "faites confiance" à l'appelant pour traiter l'objet de retour (techniquement encore modifiable) comme un NSArray immuable, c'est une option moins coûteuse que
[mutableArray copy]
.Apple est d'accord:
La pratique ci-dessus est discutée plus en détail ici:
Meilleure pratique: renvoyer mutableArray.copy ou mutableArray si le type de retour est NSArray
la source
je cherchais la réponse dans swift 3 et cette question a été montrée comme premier résultat dans la recherche et je suis inspiré de la réponse alors voici le code swift 3
la source