带有核心数据对象的 NSArray 的单例 null

Posted

技术标签:

【中文标题】带有核心数据对象的 NSArray 的单例 null【英文标题】:Singleton with NSArray of Core data objects null 【发布时间】:2015-11-19 21:08:19 【问题描述】:

所以我有一个包含 NSArray 的 Singleton。该数组由来自核心数据获取请求的 120K+ 个对象启动。当我通过数组访问视图控制器中的这些对象时,它们为空。它显示了正确数量的对象,并且在初始化后它们在单例中显示得很好。有什么想法吗?感谢您的帮助。

Singleton.h

@interface Singleton : NSObject
@property (nonatomic, retain) NSArray *singletonArray;
+(Singleton*)singleton;
@end

Singleton.m

#import "Singleton.h"
#import "DataAccessLayer.h"

@implementation Singleton
@synthesize singletonArray;
+(Singleton *)singleton 
    static dispatch_once_t pred;
    static __strong Singleton *shared = nil;
    dispatch_once(&pred, ^
        shared = [[Singleton alloc]init]; 
    );
    return shared;


-(id)init 

    if (self = [super init]) 
    
        DataAccessLayer *dataAccess = [[DataAccessLayer alloc]init];
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        [fetchRequest setEntity:[NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext: dataAccess.managedObjectContext]];
        [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"Name" ascending:YES]]];
        NSError *error = nil;
        self.singletonArray = [dataAccess.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    
    return self;

@end

ViewController.m

#import "ViewController.h"
#import "Singleton.h"

@interface ViewController ()
@end

- (void)viewDidLoad

    [super viewDidLoad]; 
    FAKFontAwesome *settingsIcon = [FAKFontAwesome gearIconWithSize:22];
    [settingsIcon addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor]];
    UIImage *settingsIconImage = [settingsIcon imageWithSize:CGSizeMake(22, 22)];

    UIButton *settingsIconButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];
    [settingsIconButton addTarget:self action:@selector(settingsBarButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [settingsIconButton setImage:settingsIconImage forState:UIControlStateNormal];
    [self.settingsBarButton setCustomView:settingsIconButton];

    self.masterArray = [NSArray new];
    self.masterArray = [[Singleton singleton] singletonArray];

    NSString *title = [[self.masterArray objectAtIndex:0] field1];
    NSLog(@"Viewdidload: %@", title);


- (IBAction)settingsBarButtonClicked:(id)sender

    NSString *title = [[self.masterArray objectAtIndex:0] field1];
    NSLog(@"SettingsBarButtonClicked Log %@", title);


@end

单例控制台输出

(lldb) po [self.singletonArray count]
120441

(lldb) po [self.singletonArray objectAtIndex:0]
<MyEntity: 0x14c0628c0> (entity: MyEntity; id: 0xd00000070e740000 <x-coredata://8DAFE4F5-7218-4F6F-B32A-1BD9C056D1B9/MyEntity/p115613> ; data: 
    "field1" = "joe";
    "field2" = "doe";
)

ViewController 中的控制台输出

 2015-11-19 17:51:09.188 MyApp[20299:7909725] Viewdidload: joe

 2015-11-19 17:54:36.637 MyApp[20334:7913246] SettingsBarButtonClicked Log (null)

(lldb) po [self.masterArray count]
120441

(lldb) po [self.masterArray objectAtIndex:0]
<MyEntity: 0x1366db7a0> (entity: <null>; id: 0xd00000070e740000 <x-coredata://8DAFE4F5-7218-4F6F-B32A-1BD9C056D1B9/MyEntity/p115613> ; data: <fault>)

【问题讨论】:

如果您查看第二个 'po` 的输出,您可以看到该对象是 fault;这意味着核心数据将在第一次访问时检索实际对象。您是否尝试过访问其中一个属性? 为什么不在 fetch 上设置批量大小?并显示视图控制器代码。 我更新了代码以显示视图控制器和日志。我确实注意到的一件事是,当在视图中调用单例时,内存会出现很大的峰值,最高可达 145mb。然后,它下降到大约 40mb。 ARC 是否会以某种方式清理单例或核心数据内容? 【参考方案1】:

在我看来,获取所有记录并将它们存储在内存中的数组中是一个非常糟糕的主意。基本上,它违背了数据库的目的。

我建议改用NSFetchedResultsController 来访问您的对象。您将免费获得很多东西:出色的性能、内存优化和许多其他功能,例如用于在保存新数据时更新您的列表,或用于填充表格视图等。

NB:从您的问题看来,数组读取得很好。尝试记录实体的实际“field1”的内容并检查它是否有效。

【讨论】:

我相信使用 Singleton 处理这么多数据的问题是内存问题。我最终创建了一个传递谓词键和值的全局 fetchRequest 方法。这允许我接收基于字段和值的过滤数组。谢谢你的建议

以上是关于带有核心数据对象的 NSArray 的单例 null的主要内容,如果未能解决你的问题,请参考以下文章

php的单例模式

Python中的单例模式

带有 NSNumber 的 NSArray 的 NSPredicate(核心数据)

spring的单例模式如何实现?

单例模式

你所不知道的单例模式和多线程并发在单例模式中的影响