2012-05-08 31 views
0

所以我有一個在Foo.h中定義的類,在Foo.m中實現。然後我有一個名爲FooController.h/m的控制器,它有多個方法將Foo與視圖對接。設置後,NSString屬性的值不會保留

美孚具有多個屬性,所以我只是要參考三種定義爲

// Foo.h 

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

正如你所看到的,富有階級Foo1這是我在其他地方所定義的屬性。我沒有完成Foo1的實現,但基本上它只是一組定義的更多屬性。 (?我沒有爲Foo1定義任何init方法莫非是個問題)Foo1的一個屬性,你應該留在你的腦海裏是:定義

// Foo1.h 

    @property (strong, nonatomic) NSString*name; 

以下美孚方法:

// 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 /平方米,我創建了一個名爲圓矩形按鈕「使隨機富」和三個標籤叫「nameLabel」,「levelLabel」「foo1Label」

之前我秀「讓隨機富」的方法(實現的底部),我應該只是展示我的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標籤保持空白並且級別標籤爲s ays(null)。 所有屬性都是合成的,但我沒有爲它們編寫自定義setter或getters。 你能幫我嗎?

我試着儘可能描述,但如果你有更多的問題,隨時提出問題!

+0

我發現Foo和Bar的這些例子很難遵循。 Foo和Foo1看起來很殘酷。什麼是makeRandomFoo方法應該做的?爲什麼它將foo作爲參數,然後重新分配它?爲什麼它會返回一個foo,而你什麼也不做? – jrturton

回答

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。另外,傳統上,您需要在創建並返回Foo的新實例時使用名稱new啓動此方法。

試試這個,在最後一行設置斷點,看看你是否可以檢查的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; 
} 
+0

真棒迴應:)我確定這是問題所在。現在我還有一個問題,我的setter方法是什麼樣的?我的意思是,名稱和級別都只是NSObjects,我不知道如何實現一個二傳手的用戶定義的類:( – brianSan

+0

@brianSan我會更新我的答案。 – trojanfoe

+0

嗯......然後,該代碼仍然不是爲我工作...我將所有內容都改爲self.name = name;等等,並且所有東西都是合成的,但它仍然顯示出相同的結果:NSStrings爲空白,NSNumber爲(null)...你認爲它是什麼可能是?? – brianSan

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

最後,根據 name屬性的實現將不包含任何東西,除非在存取器中有一個默認值,因爲你所做的全部是alloc/initing它,並且你說你沒有重寫的init方法。

+0

好吧,非常感知你:) – brianSan

+0

我是一個神祕的男人。不要誤解我的意思,我認爲開源是世界上最偉大的概念。 – brianSan