33 votes

Erreur de compilation "méthode attendue non trouvée" lors de l'utilisation de l'indice sur NSArray

J'ai écrit ce code simple pour tester la nouvelle syntaxe littérale de l'Objective-C pour les fichiers NSArray s :

NSArray *array = @[@"foo"];
NSLog(@"%@", array[0]); 

La première ligne fonctionne bien, mais la mise en indice entraîne une erreur :

La méthode attendue pour lire un élément de tableau est introuvable sur un objet de type 'NSArray *'.

Je me demande juste si j'ai fait quelque chose de mal, ou si les littéraux n'ont pas encore été complètement implémentés. Je compile avec Apple LLVM 4.0 et j'utilise le SDK iOS 5.

Voici également une capture d'écran de l'erreur.

Error

0 votes

La page sur clang.llvm.org concernant les littéraux Objective-C indique que vous devez utiliser Apple LLVM 4.0 ou clang v3.1 pour utiliser les nouvelles fonctionnalités. Avez-vous installé l'une de ces versions, et est-elle spécifiée dans vos paramètres de construction ?

0 votes

Oui, j'utilise LLVM 4.0. J'aurais dû mentionner que

3 votes

Vous devez également compiler avec les SDK iOS 6 ou OS X 10.8, faute de quoi les objets Foundation ne disposent pas des méthodes nécessaires pour l'indice de la syntaxe littérale.

36voto

Josh Caswell Points 40397

Vous devez compiler avec les SDK iOS 6 ou OS X 10.8, sinon les objets Foundation ne disposent pas des méthodes nécessaires pour l'abréviation de la syntaxe littérale*. objectAtIndexedSubscript: à mettre en œuvre par NSArray et c'est une nouvelle méthode qui a été créée pour interagir avec cette fonctionnalité du compilateur. Les parties de la nouvelle syntaxe qui ne concernent que la création d'objets devraient fonctionner correctement. Je ne pense pas que cela nécessite de nouvelles méthodes.

Pour en savoir plus http://clang.llvm.org/docs/ObjectiveCLiterals.html


*Je me base sur une recherche effectuée par borrrden : https://stackoverflow.com/a/11407844/603977

J'ai reçu beaucoup de votes positifs sur cette réponse, qui me semble vraiment fondée sur celle de Borrrden. S'il vous plaît, si vous pensez que ma réponse vaut un vote positif, cliquez et votez là aussi.

2 votes

Il y a une petite chose dont je voudrais vous avertir. Les bools littéraux ne sont pas non plus supportés à cause de cela. Cependant, une solution rapide que j'ai mise en place a été d'ajouter ceci au début de l'un de mes en-têtes communs (dans un projet iOS) -> #ifndef __IPHONE_6_0 #if __has_feature(objc_bool) #undef YES #undef NO #define YES __objc_yes #define NO __objc_no #endif #endif

1 votes

Pourquoi les souscriptions ne se réfèrent-elles pas simplement à objectAtIndex (si objectAtIndexedSubscript n'est pas trouvé, ou seulement sur -iOS6) ?

1 votes

Depuis Xcode 4.4, la nouvelle syntaxe permet toujours de déployer vers iOS 5 en appelant objectAtIndex :. Votre cible de déploiement doit être correctement définie sur 5.0 et le SDK sur la dernière version. Voir developer.apple.com/library/ios/#releasenotes/ObjectiveC/ pour une matrice de compatibilité.

15voto

Aaron Hayman Points 5421

Si vous ne visez pas iOS 6 ou OS X 10.8, je tiens à souligner qu'il est toujours remarquablement facile de faire fonctionner la soustraction. Tout ce que vous avez à faire, c'est d'ajouter les méthodes requises en tant que catégorie des classes pour lesquelles vous voulez que l'indice fonctionne, et d'implémenter ces méthodes de manière appropriée. Ainsi, ajoutez aux classes suivantes les méthodes :

NSArray : - (id)objectAtIndexedSubscript: (NSUInteger)index;

NSMutableArray : - (void)setObject: (id)obj atIndexedSubscript: (NSUInteger)index;

NSDictionary : - (id)objectForKeyedSubscript: (id)key;

NSMutableDictionary : - (void)setObject: (id)obj forKeyedSubscript: (id)key;

Pour les mettre en œuvre, il suffit d'appeler la méthode appropriée de la classe. Par exemple, pour implémenter l'inscription sur NSArray, il suffit d'implémenter :

- (id) objectAtIndexedSubscript:(NSUInteger)index{
    return [self objectAtIndex:index];
}

Le seul inconvénient que je vois est que vous devez vous assurer d'importer votre catégorie dans toute classe qui a l'intention d'utiliser l'indice. Bien sûr, vous pouvez contourner cette exigence en incluant l'élément #import dans l'en-tête de votre préfixe, généralement le fichier : <appname>-Prefix.pch . (merci à Josh Caswell de l'avoir signalé).

L'avantage est que vous pouvez modifier les méthodes d'inscription en fonction de vos besoins. Par exemple, Apple ne vous permet pas d'ajouter/supprimer des objets dans NSMutableArray à l'aide d'indices, mais cela peut être fait assez facilement :

 - (void) setObject:(id)obj atIndexedSubscript:(NSUInteger)index{
    if (index < self.count){
        if (obj)
            [self replaceObjectAtIndex:index withObject:obj];
        else
            [self removeObjectAtIndex:index];
    } else {
        [self addObject:obj];
    }
}

0 votes

"vous devez vous assurer d'importer votre catégorie dans toute classe qui a l'intention d'utiliser l'indice " Pas de problème, mettez-le dans votre en-tête de préfixe ! Bon article !

0 votes

Merci @JoshCaswell ! J'avais oublié le préfixe. J'ai modifié le message pour inclure votre information.

6 votes

Bon point, mais il est utile d'ajouter que vous n'avez pas besoin de faire cela pour cible iOS5, seulement pour compiler avec un SDK antérieur. Vous pouvez cibler iOS5 (et utiliser les nouvelles constructions) et compiler avec le SDK iOS6.

2voto

Jeff Wolski Points 3956

J'ai obtenu le code suivant de ce lien :

Vous pouvez simplement ajouter cette catégorie à NSObject et l'inscription de la collection fonctionnera. Je l'ai mis dans mon fichier .pch.

// Add support for subscripting to the iOS 5 SDK.
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
@interface NSObject (SubscriptingSupport)

- (id)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
- (id)objectForKeyedSubscript:(id)key;

@end
#endif

Bien sûr, vous aurez besoin de la dernière version de CLANG qui est déjà dans XCode 4.4.

0 votes

Cela fonctionne très bien et est très simple par rapport aux autres réponses. Merci !

0 votes

En quoi cela diffère-t-il de la réponse d'Aaron ?

0 votes

Sa réponse suggère de créer plusieurs catégories. C'est une méthode plus simple, car il suffit de créer une seule catégorie. Si cela est évident pour les développeurs expérimentés, il est probable que cela le soit moins pour les développeurs qui ne connaissent pas les catégories.

1voto

abbood Points 5959

J'ai eu le même problème, mais ce n'était pas à cause d'une mauvaise version d'iOS, mais simplement parce que le tableau d'origine était défini comme un tableau de type "A". NSArray plutôt qu'un NSMutableArray . Le changer en NSMutableArray l'a réparé pour moi

0voto

jungledev Points 386

Je l'ajoute car c'est une erreur courante qui existe encore dans Xcode à partir de 7/2015 et il n'est pas facile de trouver comment la résoudre.

J'ai reçu cette erreur lorsque j'ai tenté d'appeler une méthode sur un objet sans avoir créé une instance de cet objet. Ma solution était de créer une instance de l'objet, puis d'appeler la méthode sur la propriété sur l'instance de cet objet.

Exemple : Ce qui n'a pas marché : [self methodCall:arrayItem] (voir l'exemple complet ci-dessous)

[self tappedUser:self.activities[indexPath.row].followItem.user.givenName];

Ce qui l'a réparé : ObjectClass newObject = arrayItem ; [self methodCall:newObject] (voir l'exemple complet ci-dessous)

FollowActivityItem *followItem = self.activities[indexPath.row];
[self tappedUser:followItem.user.givenName];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X