2012-11-24 42 views
0

所以我創建了一個簡單的UITableViewController,我推入NavigationController。 我創建了一個initWithPList方法,讀取plist和的值存儲到在items@property一個NSMutableDictionary在稱爲SettingsclassNSMutableDictionary is nil

NSMutableDictionaryinitWithStyle方法中正確填充。但是在viewDidLoad,SettingsNSObjectNSMutableDictionaryitems@propertynil

我不知道我在做什麼錯誤的任何想法????

下面是一些代碼:

顯示的ViewController

TestViewController *settingsViewController = [[TestViewController alloc] initWithStyle:UITableViewStyleGrouped]; 
[[self navigationController] pushViewController:settingsViewController animated:YES] 

初始化TestViewController

- (id)initWithStyle:(UITableViewStyle)style{ 
     
       if (self = [super initWithStyle:style]) { 
                 
          // Init settings property here 
          settings = [[Settings alloc] initWithPList]; 
          // settings.items has a count of 5 here....which is correct 
       } 
       return self; 
  } 

viewDidLoadTestViewController

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
       
      // Check settings object here to see if it still has items 

     // settings.items is nil here for somereason?? 

      NSLog(@"%i", [settings.items count]); // now it's nil here? 
     
 } 

SettingsNSObject

#import <Foundation/Foundation.h> 

@interface Settings : NSObject { 

    NSMutableDictionary *items; 
    NSString *path; 
} 

@property(nonatomic, retain) NSMutableDictionary *items; 
@property(nonatomic, retain) NSString *path; 

-(id)initWithPList; 

@end 

@implementation一個片段:

@synthesize items; 
@synthesize path; 

-(id) initWithPList { 

    path = [[self documentsDirectory]stringByAppendingPathComponent:@"Settings.plist"]; 

    if(![[NSFileManager defaultManager]fileExistsAtPath:path]) 
    { 
     [[NSFileManager defaultManager]copyItemAtPath:[[NSBundle mainBundle]pathForResource:@"Settings" ofType:@"plist"] toPath:path error:nil]; 
    } 

    items = [NSMutableDictionary dictionaryWithContentsOfFile:path]; 
    return self; 
} 
+0

當你說「//初始​​設置屬性在這裏」,你在技術上不是。這個'settings'不是一個屬性引用。它是如何聲明的? (也是這個項目使用ARC?) –

+0

@PhillipMills,我猜Gabe在屬性聲明中使用了retain,這個項目是ARC之前的。 –

回答

2
@synthesize items; 

通過綜合這種方式,物業的支持伊娃被命名爲items。所以當你說

items = [NSMutableDictionary dictionaryWithContentsOfFile:path]; 

你直接分配給伊娃。在ARC手動內存管理之前,任何對伊娃的直接操作都與「保留」屬性無關。在伊娃級保留/釋放完全取決於你。

現在因爲您通過調用+dictionaryWithContentsOfFile:來創建字典,所以字典是自動發佈的。所以你已經給了一個持久變量(即伊娃)瞬態對象。噗,它走了!

解決方案是取得字典的所有權。一些便利方法沒有非autorelease等價物,所以我們必須爲它們添加retain。但在這種情況下,有一個等效的初始值設定項:

items = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; 

您擁有所有權。問題解決了。 (這也避免了向autorelease池添加任何東西。)

附加: 這對伊娃與財產具有相同的名稱仍然是令人困惑的危險。當你看到items時,很容易讓你覺得你獲得了屬性的屬性。首先,我們擺脫Ivars的明確聲明。他們不需要屬性。

@interface Settings : NSObject 

@property(nonatomic, retain) NSMutableDictionary *items; 
@property(nonatomic, retain) NSString *path; 

- (id)initWithPList; 

@end 

蘋果的慣例是在ivars前加一個下劃線。如果您使用Xcode 4.5,則完全省略@synthesize聲明。對於早期的Xcode,改變合成使用稍微不同的名稱伊娃:

@synthesize items = _items; 

然後initWithPlist可以說

_items = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; 

下劃線作爲一個提醒:「這是伊娃內存管理!是你的問題!「 (所以,你忠實release它在dealloc方法。)

+0

因此,刪除'@ interface'中的顯式ivar我明白爲什麼我應該拋棄XCode 4.5中的'@ synthesize'語句? – Gabe

+0

因爲這樣做完全等價於'@synthesize items = _items;' –

+0

我沒有意識到XCode會自動綜合4.5中的屬性......感謝您的信息。 – Gabe