0

所以我在 Foo.h 中定义了一个类,在 Foo.m 中实现。然后我有一个名为 FooController.h/m 的控制器,它有多种方法可以将 Foo 与视图接口。

Foo 有多个属性,所以我只会提到三个定义为

// Foo.h

    @property (strong, nonatomic) NSString *name;
    @property (strong, nonatomic) NSNumber *level;
    @property (strong, nonatomic) Foo1 *foo1;

如您所见,Foo 具有我在别处定义的类 Foo1 的属性。我没有完成 Foo1 的实现,但基本上它只是一组定义的更多属性。(我没有为 Foo1 定义任何 init 方法。这会是个问题吗?) Foo1 的一个属性,你应该牢记在心的是:

// Foo1.h

    @property (strong, nonatomic) NSString*name;

定义了以下 Foo 方法:

// Foo.m

    -(id) initWithName:(NSString *)name
                 level:(NSNumber *)level
                  foo1:(Foo1 *)foo1
    {
       self = [super init];
       if (self) {
         _name = name;
         _level = level;
         _foo1 = foo1;
         return self;
       }
       return nil;
    }

FooController 拥有的方法之一称为 makeRandomFoo,它生成通用名称、随机级别和静态定义的 foo1 实例(在大小意义上是静态的)。它的实现如下:

// FooController.h

    #import "Foo.h"
    #import "Foo1.h"

    @interface FooController : NSObject

    @property (strong, nonatomic) Foo *foo;

    - (Foo *)makeRandomFoo:(Foo *)foo;

// FooContoller.m

    #import <stdlib.h>

    @implementation FooController

    @synthesize foo = _foo;

    - (Foo *)makeRandomFoo:(Foo *)foo
    {
      NSString *name = @"Random Foo 1";
      NSNumber *level = [NSNumber numberWithInt:(rand() / 100)]; 
      Foo1 *foo1 = [[foo1 alloc] init];
      foo = [[foo alloc] initwithName:name
                              atLevel:level
                             withFoo1:foo1];
      return foo;
    }

然后在我的视图控制器 FooViewController.h/m 上,我创建了一个名为“Make Random Foo”的圆形矩形按钮和三个名为“nameLabel”、“levelLabel”、“foo1Label”的标签

在我展示“Make Random Foo”的方法(实现的底部)之前,我应该只展示我的 vc 的定义和实现:

// FooViewController.h

    @class Foo;
    @class FooController;

    @interface FooViewController : UIViewController

    @property (strong, nonatomic) Foo *foo;
    @property (strong, nonatomic) FooController *fooController;
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    @property (weak, nonatomic) IBOutlet UILabel *levelLabel;
    @property (weak, nonatomic) IBOutlet UILabel *foo1Label;

    - (IBAction)randomizeButton;

// FooViewController.m

    - (id)reloadView
    {
       self.nameLabel.text = self.pet.name;
       self.levelLabel.text = [NSString stringWithFormat:@"%@",self.pet.level];
       self.foo1Label.text = self.pet.foo1.name;
       (remember when I told you about a property of foo1 called name?)
    }

    - (IBAction)randomizeButton
    {
      [self.petController makeRandomFoo:self.foo];
      [self reloadView];
    }

因此,当我运行代码并点击随机按钮时,名称和 foo1 标签保持空白,而级别标签显示为 (null)。所有属性都是合成的,但我没有为它们编写和自定义 setter 或 getter。你能帮帮我吗?

我尽量做到描述性强,但如果您有更多问题,请随时提问!

4

2 回答 2

3

您没有遵循内存管理规则,因为您将初始化参数直接分配给[Foo init]. 您需要改用(合成的)setter 方法:

-(id) initWithName:(NSString *)name
                 level:(NSNumber *)level
                  foo1:(Foo1 *)foo1
{
   self = [super init];
   if (self) {
     self.name = name;
     self.level = level;
     self.foo1 = foo1;
   }
   return self;
}

由于您的实施,实例变量没有被保留,因此可能会过早释放。我们现在不想过早的任何事情,对吗?

编辑要实现您的 setter 方法(已使用@property头文件中的关键字声明),您只需使用@synthensize您已经完成的相同方式FooController

@implementation Foo

@synthesize name = _name;
@synthesize level = _level;
@synthesize foo1 = _foo1;

-(id) initWithName:(NSString *)name
... etc ...

@end

编辑 2:经过多看几眼,您似乎正在[Foo init...]使用不同命名的参数调用该方法。您还需要释放Foo1对象,因为您已将所有权传递给Foo. 同样,通常您需要在new创建并返回Foo.

试试这个并在最后一行设置一个断点,看看你是否可以检查以下属性Foo

- (Foo *)newRandomFoo:(Foo *)foo
{
    NSString *name = @"Random Foo 1";
    NSNumber *level = [NSNumber numberWithInt:(rand() / 100)]; 
    Foo1 *foo1 = [[foo1 alloc] init];
    foo = [[foo alloc] initwithName:name
                              level:level
                               foo1:foo1];
    [foo1 release];
    return foo;
}
于 2012-05-08T17:16:51.323 回答
0

根据我的猜测,这就是我认为你想做的事情(你似乎在大多数情况下都用“Foo”替换了“Pet”,但不是所有的示例代码,所以很难理解。为什么不只是发布你的真实代码?)

makeRandomFoo不应该带参数,所以应该看起来像这样:

- (Foo *)makeRandomFoo
    {
      NSString *name = @"Random Foo 1";
      NSNumber *level = [NSNumber numberWithInt:(rand() / 100)]; 
      Foo1 *foo1 = [[Foo1 alloc] init];
      Foo *foo = [[Foo alloc] initwithName:name
                              atLevel:level
                             withFoo1:foo1];
      return foo;
    }

当您从视图控制器调用它时,看起来您实际上想foo用“随机”替换视图控制器,所以它应该是:

- (IBAction)randomizeButton
    {
      self.foo = [self.petController makeRandomFoo];
      [self reloadView];
    }

最后,除非您在访问器中有默认值,否则根据属性的实现Foo1name不包含任何内容,因为您所做的只是分配/初始化它,并且您已经说过您没有覆盖的 init 方法。

于 2012-05-08T18:46:05.327 回答