2015-03-04 7 views
2

Я пытаюсь создать глобальную функцию или метод в объективе C. Это значит, что я могу назвать это с любого из моих контроллеров.Метод не найден в ObjectiveC

Я уже проверил это сообщение: How to create global functions in Objective-C

Так что я был в Xcode 6 я создал новый файл и выбрать категорию выпадающая. который создал эти два файла * .h & * .m для меня. Я добавил свой метод, называемый SaveWeatherDataNow в нем

//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 

Теперь в моем другом контроллере представления, если я называю этот метод, то компилятор не находит его вообще. Что я упустил?

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

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

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

'[NSObject SaveWeatherDataNow: XML];' должен работать. – brigadir

+0

Это было сделано. Я чувствую себя таким глупым. Можете ли вы также рассказать мне, в чем разница между + (void) и - (void) ...некоторые уроки имеют + другие - перед методами. –

+0

Если у вас есть только один объект, все будет хорошо. Если у вас разные объекты, вам нужно переключить его на - (void), чтобы он использовал данные внутреннего класса. –

ответ

1

Изменение + к - (перед (void)):

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

Таким образом, вы можете обратиться к методу внутри вашего SaveWeatherData объекта.

Не забудьте изменить его как в файле заголовка (.h), так и в файле класса (.m).

Вы также могли бы назвать

[NSObject SaveWeatherDataNow: XML];

, оставляя +.

===

При использовании +, это метод класса. Он работает во всем мире и не знает или не заботится об отдельных объектах.

Когда вы используете -, это метод объекта. Он работает в определенном объекте.

Итак, если есть кирпич класс,

+ (аннулируются) разбивают;

изменит/обновит каждый кирпич, который будет разбит.

- (void) shatter;

разрушит конкретный кирпич, на который вы отправляете это сообщение.

[myBrick1 shatter]; только разрушит один кирпич.

[Brick smash]; изменит что-то глобальное для всех кирпичей.

+0

+ предназначен для статических функций (принадлежащих классу), - для функций, принадлежащих экземплярам. – Daniel

+0

Спасибо Джеффу, пожалуйста, добавьте ответ бригады, и я пометю ваш –

2

Я пишу другой ответ, потому что я думаю, что лучшим ответом на этот вопрос будет Не делайте этого!.

Чтобы создать категорию для NSObject, чтобы сохранить данные, очень уродливая вещь.

ПОЧЕМУ

Это будет означать, что, когда вы импортировать его в класс каждый класс, который наследуется от NSObject (почти все из них), вдруг есть что дополнительный метод.

Например, такой код будет работать:

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

Если продолжать использовать статический метод (с +), вы можете сделать:

[NSObject SaveWeatherDataNow:myXmlAsString]; 

или

[NSNumber SaveWeatherDataNow:myXmlAsString]; 

или даже

[UIImage SaveWeatherDataNow:myXmlAsString]; 

Если вы измените его на метод экземпляра (с -), вы можете сделать:

[myXmlAsString SaveWeatherDataNow:myXmlAsString]; 

или

[myInt SaveWeatherDataNow:myXmlAsString]; 

или использовать большинство существующих переменных в этой области видимости, которые, казалось бы, очень странно, если не сказать больше.

ЧТО Шоуде DO ВМЕСТО

Я хотел бы использовать один из следующих 2 варианта:

  1. Создать класс, который управляет данными сохранения/загрузки для вас. Использование должно выглядеть следующим образом:

    [DataManager saveWeatherDataNow:myXmlAsString];

  2. Если вам не нужно так много, только эту функцию, вы можете создать класс Utility и добавить, что статический метод (в случае, если вы не один уже).

    [Utility saveWeatherDataNow:myXmlAsString];

PS: по соглашению, вы обычно начинаются имена методов с строчными буквами.

+0

. Привет, можете ли вы немного рассказать о том, почему следует использовать класс Vs. Я имею в виду, если я создам глобальный метод, они оба будут делать то же самое. Является ли это более эффективным во время выполнения, чем другое? Лучше ли производительность с тем, чем другим, или просто хорошим соглашением всегда использовать класс вместо категории? Извините, я просто пытаюсь понять. –

+0

Не всегда можно использовать класс над категорией, это зависит от того, что вы делаете. Классы и методы представляют собой идею. Класс - это тип объекта (например, автомобиль), и метод - это то, что объект может делать (например, открытые двери). Вы говорите, что каждый объект может сохранять данные о погоде (автомобиль или банановые данные о погоде?). С точки зрения идеи это просто не имеет смысла. Вы должны попробовать иметь архитектуру, которая имеет смысл, поэтому ее можно поддерживать. Если бы вы добавили все функции в категорию NSObject, вы получите все объекты, имеющие миллионы функций. – Daniel

+0

Таким образом, вы никогда не сможете найти те, которые действительно принадлежат объекту, и вы полностью потеряете свой собственный код. – Daniel

0

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

Корень проблемы здесь является то, что вы не определили класс под названием SaveWeatherData. Вместо этого вы создали категорию на NSObject, так что вы можете позвонить +SaveWeatherDataNow: в любой класс, полученный из NSObject. Прямым решением является создание класса вместо категории. Измените эти строки:

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

к ним:

@interface SaveWeatherData 
@implementation SaveWeatherData 

и что должно позволить вызов, как это:

[SaveWeatherData SaveWeatherDataNow:XML]; 

работать правильно.

+0

Эй, Калеб, есть ли опечатка в вашем ответе? Если я укажу свой класс как @interface SaveWeatherData, я получаю предупреждение о том, что класс SaveWeatherData определен без указания базового класса. –

Смежные вопросы