从类或方法访问对象

时间:2013-02-09 08:32:15

标签: objective-c cocoa

我的Cocoa项目(Xcode)中有2个类。第一个是AppDelegate类,第二个是Book类。

在我的Book类中,我在@interface中设置了一个整数属性,这是本书的章节。在@implementation中,我创建了对象(例如Book * firstBook = [[book alloc] init])并设置了它们的属性(在Book.m文件中)。这些是我的数据,不会改变。

在我的app委托中,我有一个方法可以获取用户从界面项中选择的内容,获取所选项的标题,谁的名称将与Book.m中的名称相同。然后运行for循环以创建popUpButton的菜单项,以便用户可以选择要跳转到的章节。

我现在看到的问题是,当我尝试运行for循环来创建菜单项时,我需要限制循环量。该限制数量基于selectedObjectByUser的chapter属性(在Book.m中列出)。我该如何访问它。

我确信如果我可以将这两者连接在一起是可行的,因为它在此方法中创建对象时有效(在AppDelegate.h下),但问题是它太占用空间而且经常更改。

1 个答案:

答案 0 :(得分:3)

我不完全确定这里的情况如何,但让我们先看看一些示例代码。

//// Book.h
@interface Book : NSObject

@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *author;
@property (nonatomic, assign) NSInteger numberOfPages;

- (id)initWithTitle:(NSString *)aTitle andAuthor:(NSString *)anAuthor;

@end


//// Book.m
@implementation Book

- (id)initWithTitle:(NSString *)aTitle andAuthor:(NSString *)anAuthor {
    if ( self = [super init] ) {
        self.title = aTitle;
        self.author = anAuthor;
    }
    return self;
}

- (void)dealloc {
    self.title = nil;
    self.author = nil;
    [super dealloc];
}

@end

因此,在此我们建立一个类并为其提供3个属性,title和author(它们都是NSString的)和numberOfPages(它是一个整数)。在课堂上,我们可以通过调用诸如self.propertyName = value

之类的东西来操纵这些值

这一切都很好,但究竟发生了什么?好吧,让我们更新标题:

//// Book.h
@interface Book : NSObject {
@private
    NSString *_title;
    NSString *_author;
    NSInteger _numberOfPages;
}

@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *author;
@property (nonatomic, assign) NSInteger numberOfPages;

- (id)initWithTitle:(NSString *)aTitle andAuthor:(NSString *)anAuthor;

@end

在这里,我们刚刚明确定义了编译器通常会通过@property构造推断出的东西。这些新添加的内容是我们所说的实例变量或ivars,它们是您实际存储分配给属性的值的位置。

然而,如果你还不是100%熟悉内存管理,那么操纵ivars会很危险。即使您使用ARC,您仍应了解该管理的工作原理。

所以我们现在已经公开了这些属性实际存储数据的位置,但那个@private工作呢?它有什么关系? @private是一系列关键字的一部分,有助于表示某些内容的“辅助功能范围”。此系列中的其他两个关键字是@protected@public,但是如果不常见,则使用后两个关键字很少见。这些关键字负责说明您可以访问的位置。这是对它们的快速定义。

  • @public 可以从任何地方自由访问,甚至可以在对象本身之外。但是,在Cocoa开发世界中,通常认为直接从其自己的类外部访问实例变量是非常糟糕的做法,因此为什么你会发现很少有关于如何做到这一点。

  • @protected 可在类及其自己的子类中自由访问。无法在类/对象之外访问。

  • @private 可以在课堂上自由访问,但不能在其他任何地方访问。不能在类/对象之外或甚至在其子类中访问。

现在我们已经介绍了实际驱动属性背后存储的内容,让我们看一下在应用的其他部分使用我们的Book对象,例如AppDelegate

//// AppDelegate.m
@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    Book *myBook = [[Book alloc] initWithTitle:@"pending title" andAuthor:@"Foo Bar"];

    myBook.title = @"My Cool Book";

    NSLog(@"%@ by %@", myBook.title, myBook.author);

    [myBook release];
}

@end

在这里我们创建一个新的Book对象,用更多技术术语来表示,我们定义一个名为myBook的变量,其类型为Book并实例化它。在这里我们使用我们之前创建的-initWithTitle:andAuthor:方法,以告诉Book对象它应该有一个初始标题和作者。

按照这条线,我们会更加好奇。 myBook.title = @"My Cool Book";您可能还记得我们在Book.m中有类似的内容,self.title = aTitle。那么这里发生了什么?为什么我们现在使用myBook而不是自己,就像我们之前做的那样?原因是因为实际上是自我。

self是Objective-C运行时提供的关键字,它引用您所在的当前对象。因此,如果我们在Book.m中编写代码,self将引用当前的Book对象。如果我们在AppDelegate.m中使用self,它将引用AppDelegate。所以在我们之前的代码中,self指的是当前的Book对象,就像我们的myBook对象现在引用一个特定的Book对象一样。它们基本上彼此相等(不完全是,但这是另一个讨论领域)。

这意味着可以通过myBook变量访问Book或方法中的任何属性,就像在Book.m中使用self一样。所以我们也可以这样做

myBook.title = @"My Book";
myBook.author = @"Baz Quux";
myBook.numberOfPages = 100;

希望这有帮助(并回答你的问题,如果没有,那么它可以作为对希望了解更多属性和实例变量的人的参考)