1

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

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

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

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

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

4

1 回答 1

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是一系列关键字的一部分,这些关键字有助于表示某物的“可访问性范围”。该系列中的其他两个关键字是@protectedand @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 对象,用更专业的术语来说,我们定义了一个名为myBookof的变量Book并实例化它。在这里,我们使用-initWithTitle:andAuthor:我们之前创建的方法来告诉 Book 对象它应该有一个初始标题和作者。

沿着这条线,我们会得到一些更奇怪的东西。myBook.title = @"My Cool Book";您可能还记得我们在 Book.m 中有类似的东西,self.title = aTitle. 那么这里发生了什么?为什么我们现在使用 myBook 而不是 self ,就像我们以前那样?原因是因为自我实际上是什么。

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;

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

于 2013-02-09T09:16:36.370 回答