Objective-C中的公共范围?

时间:2009-06-29 05:32:40

标签: iphone objective-c

我确信这是一个简单的问题,但到目前为止它一直难以捉摸,而且我很难过......

如何声明Ivar以便可以从项目中的所有类访问它?

[不知道它是否重要,但有问题的ivar是我的Model类的一个实例,其数据需要可供各种视图控制器访问。]

我可以在 Objective-C 2.0编程语言"The Scope of Instance Variables”告诉我 ......这将是使用“@public”指令。

所以我在声明了ivar的@interface块中尝试了这个:

@interface ...

...

@public
ModelClass *theModel;

@end

...但是当我尝试在另一个类中引用“theModel”时,编译器不会自动完成,当我以任何方式输入它时,编译器会显示: “错误:'theModel'未声明(首次使用此功能)”。

我认为这是一个范围问题,而且我没有适当地提供ivar,但是如何?不知何故,我需要访问它,或以某种方式使其指针可用。

任何想法都会非常感激。非常感谢!

6 个答案:

答案 0 :(得分:5)

也许您忘了将实例变量放在所有实例变量声明所在的类的大括号内?

@interface Foo : NSObject {

    // other instance variable declarations

    @public
    ModelClass *theModel;
}

// method and property declarations

@end

另外,您能否向我们展示您如何尝试从其他地方访问实例变量的代码?正确的语法应该是:

myFooInstance->theModel

其中myFooInstance是“Foo *

类型的值

答案 1 :(得分:3)

您无法从任何其他类访问iVars。

你必须声明一个getter / setter方法来改变或查看另一个类的变量 - 你真正想要的是属性,这样可以更容易地定义和访问这些getter / setter方法。

在上面的示例中,您将在定义头文件中的局部变量的块之后定义属性:

@property (nonatomic, retain) ModelClass *theModel;

在实现文件中,您将在@implementation行之后使用@synthesize语句创建getter / setter:

@synthesize theModel;

然后,如果您创建了类的实例,则可以像下面这样访问类实例变量:

myInstance.theModel = [[[ModelClass alloc] init] autorelease];

@public& @private用于定义子类的可见性(该类的扩展也可以获取超类定义的所有类本地变量),而不是任何随机类。

答案 2 :(得分:3)

我通过表示我的数据模型的单例,使Tab Bar管理的所有视图都可以使用属性。这是有效的,并允许所有视图访问数据(以及任何其他应用程序元素。创建单例是直截了当的(SO上有大量示例)。您只需请求实例并获取所需的属性值。

这是创建Singleton的框架。关键点是静态实例以及初始化为[[self alloc] init];的事实。这将确保正确清理对象。该类底层的所有方法都是SDK Docs的标准方法,以确保忽略发布调用(因为该对象是全局共享的)。

Singleton Boilerplate(ApplicationSettings.m):

static ApplicationSettings *sharedApplicationSettings = nil;

+ (ApplicationSettings*) getSharedApplicationSettings
{
    @synchronized(self) {
        if (sharedApplicationSettings == nil) {
            [[self alloc] init]; // assignment not done here
        }
    }
    return sharedApplicationSettings;
}

+ (id)allocWithZone:(NSZone *)zone
{
    @synchronized(self) {
        if (sharedApplicationSettings == nil) {
            sharedApplicationSettings = [super allocWithZone:zone];
            return sharedApplicationSettings;  // assignment and return on first allocation
        }
    }
    return nil; //on subsequent allocation attempts return nil
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (unsigned)retainCount
{
    return UINT_MAX;  //denotes an object that cannot be released
} 

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

答案 3 :(得分:1)

标准的Objective-C方法是使用返回ivar的类方法

在你的.h文件中:

+ (id)defaultModel;

并在您的.m文件中:

static ModelClass * defaultModelInstance;

@implementation ModelClass

+ (id)defaultModel {
    if (!defaultModelInstance) {
        defaultModelInstance = [[ModelClass alloc] init];
    }
    return defaultModelInstance;
}

@end

虽然如果你需要一个特定的ivar而不仅仅是“一个总是相同的ivar”,这需要调整

许多Cocoa类使用这种类型的设计,即[NSWorkspace sharedWorkspace]

答案 4 :(得分:0)

想一个C全局变量。

添加:
extern ModelClass* theModel;
在标题中的@end之后,只要您包含标题,变量就会显示。

在ModelClass.cpp文件中添加:
    ModelClass* theModel;
在课前实施。

在您分配并初始化变量之前,变量的值仍然为nil,并且您将负责确保在正确的时间取消分配。

答案 5 :(得分:0)

感谢大家就此主题进行非常有益的讨论!显然,有几种方法可以在这里处理,所以这是一种非常有用的技术分类。


只是让大家都知道,在进一步研究这个问题时,我遇到了一些其他非常有用的页面,如下所示。它们包括我之前从未听说过的NSNotificationCenter;以及“依赖注入”设计模式的想法。

这个想法是在类之间保持“低耦合”(1),使代码更加模块化。更适合单元测试。

虽然'通知'模式听起来像个好主意,但在这种情况下它可能有点矫枉过正,考虑到我在应用程序运行期间只需要一个数据模型实例,并且它不会改变整个

最后,即使Apple的 Obj-C 指南(2)中详细记载了“@public”编译器指令,我后来在另一个文档中发现了一个引人入胜的法令,声明它不应该使用!引自Apple自己的 Cocoa Fundamentals (3):
“为你的实例变量赋予适当的范围。永远不要将变量作为@public范围,因为这违反了封装原则。......” (奇怪的是他们没有在他们的'Objective-C 2.0'指南中提到这个指令实际解释过。)

无论如何,这里有一些其他链接我发现也充满了一些很棒的见解。供参考:

  • S.O。:“什么是最好的方法 沟通之间 viewcontrollers?“(4)<<

  • CocoaWithLove:“五种方法 倾听,观察和通知 可可“(5)

  • CocoaWithLove:“单身人士, AppDelegates和顶级数据“(6)


希望这些帮助。无论如何,再次感谢大家!

最佳, ROND

P.S。哎呀!它不会让我发布多个内联超链接,所以我在这里列出它们。显然,它们的前缀都是“http://”......:O

(1):en.wikipedia.org/wiki/Coupling_(computer_science)
  (2):developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple%5Fref/doc/uid/TP30001163-CH12-TPXREF127
  (3):developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/AddingBehaviortoaCocoaProgram/AddingBehaviorCocoa.html#//apple_ref/doc/uid/TP40002974-CH5-SW12
  (4):stackoverflow.com/questions/569940/whats-the-best-way-to-communicate-between-viewcontrollers
  (5):cocoawithlove.com/2008/06/five-approaches-to-listening-observing.html
  (6):cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html