设置后,NSString属性的值不会保留

时间:2012-05-08 17:05:50

标签: objective-c

所以我有一个在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;
    }

然后在我的viewcontroller上,FooViewController.h / m,我创建了一个名为“Make Random Foo”的圆形rect按钮和三个名为“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。 你能救我一下吗?

我尝试尽可能具有描述性,但如果您有更多问题,请随时提出要求!

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

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

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];
    }

最后,根据Foo1的实现,name属性将不包含任何内容,除非您在访问者中有默认值,因为您所做的只是分配/启动它而您拥有说你没有重写的init方法。