2015-03-04 2 views
2

J'essaie de créer une fonction globale ou une méthode dans objectiveC. C'est ainsi que je peux l'appeler de n'importe lequel de mes contrôleurs de vue.Méthode introuvable dans ObjectiveC

je l'ai déjà vérifié ce post: How to create global functions in Objective-C

Alors ce que je faisais était dans Xcode 6 J'ai créé nouveau fichier et choisissez une catégorie déroulant. qui a créé ces deux fichiers * .h & * .m pour moi. J'ai ajouté ma méthode appelée SaveWeatherDataNow en elle

//NSObject+SaveWeatherData.h 
#import <Foundation/Foundation.h> 

@interface NSObject (SaveWeatherData) 

+(void)SaveWeatherDataNow:(NSString *)XML; 

@end 

//NSObject+SaveWeatherData.m 
#import "NSObject+SaveWeatherData.h" 

@implementation NSObject (SaveWeatherData) 

+(void)SaveWeatherDataNow:(NSString *)XML 
{ 

    NSLog(@"SaveWeatherDataNow XML lenght: %ld", [XML length]); 
} 

@end 

Maintenant, dans mon autre contrôleur de vue si j'appelle cette méthode alors complier ne trouve pas du tout. Qu'est-ce que j'ai raté?

// v1CitiesAdd.m 
#import "NSObject+SaveWeatherData.h" 

@implementation v1CitiesAdd 
... 
... 
-(IBAction) doneAction 
{ 

... 
[SaveWeatherData SaveWeatherDataNow:XML]; // Complier Error: Use of undeclared identifier SaveWeatherData 
+3

'[NSObject SaveWeatherDataNow: XML];' devrait fonctionner. – brigadir

+0

C'est ce qu'il a fait. Je me sens si bête. Pouvez-vous également me dire quelle est la différence entre + (vide) et - (vide) ...certains tutoriels ont + d'autres ont - en face des méthodes. –

+0

Si vous avez un seul objet, ça ira. Si vous avez des objets différents, vous devrez passer à - (void) pour utiliser les données de la classe interne. –

Répondre

1

Modifier le + à un - (devant (void)):

-(void)SaveWeatherDataNow:(NSString *)XML; 

De cette façon, vous pouvez vous référer à la méthode de votre objet SaveWeatherData. N'oubliez pas de le changer à la fois dans le fichier d'en-tête (.h) et dans le fichier de classe (.m).

Vous pouvez également appeler

[NSObject SaveWeatherDataNow: XML];

en laissant le signe +.

===

Lorsque vous utilisez un +, il est une méthode de classe. Cela fonctionne globalement, et ne sait pas ou ne se soucie pas des objets individuels.

Lorsque vous utilisez un -, il s'agit d'une méthode d'objet. Cela fonctionne dans un objet spécifique.

Donc, s'il y a une classe de briques,

+ (void) fracasser;

changerait/mettrait à jour chaque brique à briser.

- (vide) briser;

va briser une brique spécifique à laquelle vous envoyez ce message.

[myBrick1 shatter]; ne ferait que briser la seule brique.

[Smash smash]; changerait quelque chose globalement pour toutes les briques.

+0

+ est pour les fonctions statiques (qui appartiennent à une classe), - est pour les fonctions qui appartiennent aux instances – Daniel

+0

Merci Jeff, s'il vous plaît ajouter la réponse de brigade et je vais marquer le vôtre –

2

J'écris une réponse différente, parce que je pense que la meilleure réponse à cette question serait Ne le faites pas!.

Pour créer une catégorie pour NSObject pour enregistrer des données est une chose très laide à faire.

POURQUOI

Cela voudrait dire que lorsque vous importez à une classe de la classe qui hérite de NSObject (presque tous) aurait tout à coup cette méthode supplémentaire.

Par exemple, le code comme ceci fonctionnerait:

NSNumber *myInt = @(3) 
NSString *myXmlAsString = [NSString stringWithFormat:@"<rating>%@</rating>",myInt.integerValue]; 

Si vous continuez à utiliser la méthode statique (avec +), vous pouvez faire:

[NSObject SaveWeatherDataNow:myXmlAsString]; 

ou

[NSNumber SaveWeatherDataNow:myXmlAsString]; 

ou même

[UIImage SaveWeatherDataNow:myXmlAsString]; 

Si vous changez à une méthode d'instance (avec -), vous pouvez faire:

[myXmlAsString SaveWeatherDataNow:myXmlAsString]; 

ou

[myInt SaveWeatherDataNow:myXmlAsString]; 

ou utiliser la plupart des variables existantes dans ce cadre, ce qui semble très étrange à dire le moins.

CE QUE VOUS SHOUD DO INSTEAD

j'utiliser une des 2 options suivantes:

  1. Créer une classe qui gère l'épargne des données/chargement pour vous. L'utilisation devrait alors ressembler à ceci:

    [DataManager saveWeatherDataNow:myXmlAsString];

  2. Si vous n'avez pas besoin d'autant, que cette fonction, vous pouvez créer une classe utilitaire et ajouter cette méthode statique (au cas où vous ne disposez pas d'un déjà).

    [Utility saveWeatherDataNow:myXmlAsString];

PS: par convention, vous commencez généralement des noms de méthode avec les minuscules.

+0

Salut, pouvez-vous élaborer un peu pour savoir pourquoi utiliser une catégorie classe Vs. Je veux dire que si je crée une méthode globale, ils feront tous les deux la même chose. Est-ce que l'un est plus efficace à l'exécution que l'autre? Y at-il une meilleure performance avec l'un que l'autre ou c'est juste une bonne convention de toujours utiliser la classe au lieu de la catégorie? Désolé, j'essaie juste de comprendre. –

+0

Il n'est pas toujours préférable d'utiliser la classe plutôt que la catégorie, cela dépend de ce que vous faites. Les classes et les méthodes représentent une idée. Une classe est un type d'objet (comme une voiture) et une méthode est quelque chose que cet objet peut faire (comme des portes ouvertes). Ce que vous dites est que chaque objet peut sauver des données météorologiques (une voiture ou une banane sauver des données météorologiques ??). Du point de vue de l'idée, cela n'a aucun sens. Vous devriez essayer d'avoir une architecture logique, afin qu'elle puisse être maintenue. Si vous deviez ajouter toutes les fonctions à une catégorie de NSObject, vous finiriez avec tous les objets ayant des millions de fonctions. – Daniel

+0

Ainsi, vous ne serez jamais capable de trouver ceux qui appartiennent vraiment à l'objet, et vous serez complètement perdu dans votre propre code. – Daniel

0

[SaveWeatherData SaveWeatherDataNow:XML]; // Complier Error: Use of undeclared identifier SaveWeatherData

La racine du problème est ici que vous n'avez pas défini une classe nommée SaveWeatherData. Au lieu de cela, vous avez créé une catégorie sur NSObject, de sorte que vous pouvez appeler le +SaveWeatherDataNow: sur n'importe quelle classe dérivée de NSObject. La solution directe consiste à créer une classe au lieu d'une catégorie. Changer ces lignes:

@interface NSObject (SaveWeatherData) 
@implementation NSObject (SaveWeatherData) 

à ces:

@interface SaveWeatherData 
@implementation SaveWeatherData 

et qui devrait permettre à un appel comme celui-ci:

[SaveWeatherData SaveWeatherDataNow:XML]; 

pour fonctionner correctement.

+0

Salut Caleb, est-ce qu'il y a une faute de frappe dans ta réponse? Si je spécifie ma classe en tant que @interface SaveWeatherData, j'obtiens un avertissement de génération que Class SaveWeatherData est défini sans spécifier une classe de base. –