Цель C, Ошибка связывания с внешней переменной - PullRequest
1 голос
/ 17 февраля 2011

У меня есть очень простой код Java, как этот. Я понятия не имею, как это сделать в Objective C. Особенно, статическая часть, которая вызывает метод getLocalAddress () и присваивает его статической строковой переменной. Я знаю, как установить статическую переменную и статический метод в Objective, но я не знаю, как реализовать эту статическую {} часть в Java. Заранее спасибо ...

public class Address {

     public static String localIpAddress;

    static {
        localIpAddress =  getLocalIpAddress();
    }

    public Address() {

    }

    static String getLocalIpAddress() {
         //do something to get local ip address
     }

}

Я добавил это в свой .h файл

 #import <Foundation/Foundation.h>

 extern NSString *localIpAddress;

 @class WifiAddrss;

 @interface Address : NSObject {

 }

 @end

И мой .m файл выглядит как

 #import "Address.h"
 #import "WifiAddress.h"

 @implementation Address

 +(void)initialize{
     if(self == [Address class]){
         localIpAddress = [self getLocalIpAddress];
     }
 }

 +(NSString *)getLocalIpAddress{
      return address here
 }

 -(id)init{    
     self = [super init];
     if (self == nil){
         NSLog(@"init error");
     }

     return self;
 }
 @end

И теперь я получаю ошибку компоновки, и она жалуется на часть "extern NSString * localIpAddress". Если я изменяю extern на static, он работает нормально. Но я хотел сделать так, чтобы область действия переменной localIpAddress была помечена как grobal. Поскольку, если я поставлю «static» перед переменной в Objective-C, то эта переменная будет видна только в классе. Но на этот раз я хочу сделать это как переменную. Поэтому мой вопрос заключается в том, как сделать переменную localIpAddress как переменную типа grobal, которая инициализируется один раз при первом создании класса Address. Заранее спасибо ...

Ответы [ 3 ]

3 голосов
/ 17 февраля 2011

Вы объявили переменную в своем файле .h (сообщили компилятору, что она существует и какого типа она есть), теперь вам нужно определить ее в своем файле .m (фактически сделать так, чтобы она существовала).

Просто добавьте NSString *localIpAddress; в ваш файл .m или, что еще лучше:

NSString *localIpAddress = nil;

(то есть, дать ему нормальное значение по умолчанию)

Ключевое слово extern означает: переменная с указанным именем и типом существует, но на самом деле находится во «внешнем» файле, который необходимо связать. Таким образом, для каждого объявления extern вам необходимо определить переменную в одном из ваших файлов реализации (.c, .cxx / .c ++ /. Cpp, .m; этот механизм является частью стандарта C, для которого Objective-C стоит).

1 голос
/ 17 февраля 2011

Если вы не хотите, чтобы другие модули обращались к localIpAddress напрямую, без использования вашего класса, объявите его как static в файле вашей реализации (.m).

extern следует использовать в следующем сценарии:

  • Модуль определяет переменную как глобальную. Эта конкретная единица перевода не должна использовать extern
  • Другие модули должны обращаться к этой переменной напрямую. Эти конкретные единицы перевода должны использовать extern

Поскольку это не ваш случай, сделайте следующее в вашем файле реализации (.m):

static NSString *localIpAddress;

// …

+(NSString *)getLocalIpAddress{
    return localIpAddress;
}

и удалить

extern NSString *localIpAddress;

из файла заголовка (.h).

Всякий раз, когда вам нужно получить этот адрес, используйте

NSString *addr = [Address getLocalIpAddress];

Кстати, соглашение заключается в том, что методы получения не начинаются с get. Например, вы могли бы назвать этот метод localIpAddress.

0 голосов
/ 17 февраля 2011

Быстрое решение проблемы - переместить переменную localIpAddress в файл реализации.Тогда вам не нужно будет использовать ключевое слово extern.На самом деле, если вы подумаете об этом, у вас есть статический метод доступа, поэтому нет смысла иметь само объявление переменной в заголовке.

Позвольте мне уточнить:

Интерфейс:

#import <Foundation/Foundation.h>

@interface Address : NSObject {

}

+(void) initializeLocalIpAddress;

+(NSString *) localIpAddress;

@end

Реализация:

#import "Address.h"
#import "WifiAddress.h"

NSString *localIpAddress;

@implementation Address

+(void) initializeLocalIpAddress
{
    //get the local ip address here
    localIpAddress = ...;
}

+(NSString *) localIpAddress
{
    return localIpAddress;
}

-(id)init {    
     if ((self = [super init])) {
         NSLog(@"init error");
     }
     return self;
 }
 @end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...