web-dev-qa-db-fra.com

Créer un tableau de propriétés d'entiers dans Objective C

J'ai des problèmes pour créer une propriété d'un tableau d'entiers dans Objective C . Je ne sais pas si c'est même possible de le faire dans Obj-C, alors j'espère que quelqu'un pourra m'aider à trouver comment de le faire correctement ou de proposer une solution alternative.

myclass.h

@interface myClass : NSObject {

@private int doubleDigits[10];
}

@property int doubleDigits;
@end

myclass.m

@implementation myClass

    @synthesize doubleDigits;
    -(id) init {

        self = [super init];

        int doubleDigits[10] = {1,2,3,4,5,6,7,8,9,10};

        return self;
    }

    @end

Lorsque je compile et exécute, j'obtiens le message d'erreur suivant:

erreur: type de propriété 'doubleDigits' ne correspond pas au type d'ivar 'doubleDigits'

J'espère que quelqu'un pourra apporter une solution ou me guider dans la bonne direction.

Merci d'avance.

58
woopstash

Cela devrait fonctionner:

@interface MyClass
{
    int _doubleDigits[10]; 
}

@property(readonly) int *doubleDigits;

@end

@implementation MyClass

- (int *)doubleDigits
{
    return _doubleDigits;
}

@end
30
robottobor

Les tableaux C ne font pas partie des types de données pris en charge pour les propriétés. Voir "Le langage de programmation Objective-C" dans la documentation Xcode, à la page Propriétés déclarées:

Types supportés 

Vous pouvez déclarer une propriété pour tout Classe Objective-C, Core Foundation type de données ou «données anciennes simples» (POD) type (voir Langage C++ Remarque: Types de POD ). Pour les contraintes sur l'utilisation de Core Les types de fondations, cependant, voir “Noyau Fondation."

POD n'inclut pas les tableaux C. Voir http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html

Si vous avez besoin d'un tableau, vous devez utiliser NSArray ou NSData. 

À mon avis, les solutions de contournement consistent à utiliser (void *) pour contourner la vérification de type. Vous pouvez le faire, mais cela rend votre code moins facile à gérer.

20
lucius

Comme Lucius l'a dit, il n'est pas possible d'avoir une propriété de tableau C. Utiliser une NSArray est la voie à suivre. Un tableau ne stocke que des objets, vous devez donc utiliser NSNumbers pour stocker votre ints. Avec la nouvelle syntaxe littérale, l'initialisation est très facile et directe:

NSArray *doubleDigits = @[ @1, @2, @3, @4, @5, @6, @7, @8, @9, @10 ];

Ou:

NSMutableArray *doubleDigits = [NSMutableArray array];

for (int n = 1; n <= 10; n++)
    [doubleDigits addObject:@(n)];

Pour plus d'informations: Référence de classe NSArray , Référence de classe NSNumber , Syntaxe littérale

16
Tim Vermeulen

Je ne fais que spéculer:

Je pense que la variable définie dans les ivars alloue l'espace directement dans l'objet. Cela vous empêche de créer des accesseurs car vous ne pouvez pas attribuer un tableau par valeur à une fonction, mais uniquement via un pointeur. Par conséquent, vous devez utiliser un pointeur dans les ivars:

int *doubleDigits;

Et ensuite, allouez l’espace correspondant dans la méthode init:

@synthesize doubleDigits;

- (id)init {
    if (self = [super init]) {
        doubleDigits = malloc(sizeof(int) * 10);
        /*
         * This works, but is dangerous (forbidden) because bufferDoubleDigits
         * gets deleted at the end of -(id)init because it's on the stack:
         * int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
         * [self setDoubleDigits:bufferDoubleDigits];
         *
         * If you want to be on the safe side use memcpy() (needs #include <string.h>)
         * doubleDigits = malloc(sizeof(int) * 10);
         * int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
         * memcpy(doubleDigits, bufferDoubleDigits, sizeof(int) * 10);
         */
    }
    return self;
}

- (void)dealloc {
    free(doubleDigits);
    [super dealloc];
}

Dans ce cas, l'interface ressemble à ceci:

@interface MyClass : NSObject {
    int *doubleDigits;
}
@property int *doubleDigits;

Modifier:

Je ne sais vraiment pas si c'est permis, est-ce que ces valeurs sont vraiment sur la pile ou sont-elles stockées ailleurs? Ils sont probablement stockés dans la pile et ne peuvent donc pas être utilisés en toute sécurité dans ce contexte. (Voir la question sur les listes d'initialisation )

int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
[self setDoubleDigits:bufferDoubleDigits];
12
Georg Schölly

Cela marche 

@interface RGBComponents : NSObject {

    float components[8];

}

@property(readonly) float * components;

- (float *) components {
    return components;
}
6
Martin West

Vous pouvez mettre ceci dans votre fichier .h pour votre classe et le définir comme propriété, dans XCode 7: 

@property int  (*stuffILike) [10];
1

J'ai trouvé toutes les réponses précédentes trop compliquées ... J'ai eu le besoin de stocker un tableau de quelques ints en tant que propriété et j'ai trouvé que la nécessité pour ObjC d'utiliser un NSArray était une complication inutile de mon logiciel.

Alors j'ai utilisé ceci:

typedef struct my10ints {
    int arr[10];
} my10ints;

@interface myClasss : NSObject

@property my10ints doubleDigits;

@end

Cela se compile proprement en utilisant Xcode 6.2.

Mon intentionétaitde l'utiliser comme ceci:

myClass obj;
obj.doubleDigits.arr[0] = 4;

CEPENDANT, cela ne fonctionne pas . C'est ce que cela produit:

int i = 4;
myClass obj;
obj.doubleDigits.arr[0] = i;
i = obj.doubleDigits.arr[0];
// i is now 0 !!!

La seule façon d'utiliser ceci correctement est:

int i = 4;
myClass obj;
my10ints ints;
ints = obj.doubleDigits;
ints.arr[0] = i;
obj.doubleDigits = ints;
i = obj.doubleDigits.arr[0];
// i is now 4

et ainsi, défait complètement mon point (en évitant la complication d'utiliser un NSArray).

0
gog