0

だから私は私がUITableViewControllerにプッシュする単純なものを作成しましたNavigationControllerinitWithPListを読み取り、呼び出された内の にplist値を格納するメソッドを作成しました。NSMutableDictionaryitems @propertyclassSettings

NSMutableDictionaryがメソッドに正しく取り込まれますinitWithStyle。ただし、中古品のviewDidLoad場合はNSMutableDictionary items @property中古品Settings NSObjectですnil

私は何を間違っているのか分かりません。

ここにいくつかのコードがあります:

表示中 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;
  }

viewDidLoad のために TestViewController

- (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?
    
 }

Settings NSObject_

#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;  
}
4

1 に答える 1

2
@synthesize items;

このように合成することで、プロパティのバッキング ivar は という名前になりitemsます。だからあなたが言うとき

    items = [NSMutableDictionary dictionaryWithContentsOfFile:path];

ivarに直接割り当てています。ARC以前の手動メモリ管理では、ivarの直接操作は「保持」プロパティとは関係ありません。ivar レベルでの保持/解放は完全にあなた次第です。

を呼び出して辞書を作成しているため+dictionaryWithContentsOfFile:、辞書は自動解放されます。つまり、永続変数 ( itemsivar) に一時オブジェクトを指定しました。ふふっ、なくなった!

解決策は、ディクショナリの所有権を取得することです。一部の便利なメソッドには、autorelease 以外の等価物がないため、retainそれらに a を追加する必要があります。ただし、この場合、同等の初期化子があります。

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

あなたには所有権があります。問題が解決しました。(これにより、自動解放プールへの追加も回避されます。)

おまけ: ivar がプロパティと同じ名前を持つことは、依然として紛らわしいほど危険です。が表示されるたびに、プロパティの属性を取得していると考えるのは簡単ですitems。まず、ivar の明示的な宣言を取り除きましょう。プロパティには必要ありません。

@interface Settings : NSObject

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

- (id)initWithPList;

@end

Apple の規則では、ivar の前にアンダースコアを付けます。Xcode 4.5 を使用している場合は、@synthesizeステートメントを完全に省略してください。以前の Xcode では、合成を変更して、ivar に少し異なる名前を使用します。

@synthesize items = _items;

それからinitWithPlist言うことができます

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

アンダースコアは、「これが ivar です! メモリ管理が問題です!」というリマインダーとして機能します。(そして、あなたは忠実releasedeallocメソッドでそれを行います。)

于 2012-11-24T18:14:41.850 に答える