我刚遇到这个问题
+ (NSArray *)fetchMyStuffInContext:(NSManagedObjectContext *)_moc
{
NSFetchRequest *request;
NSPredicate *pred;
__block NSError *error;
__block NSArray *myStuff;
request = [[NSFetchRequest alloc] initWithEntityName:@"myobs"];
pred = [NSPredicate predicateWithFormat:@"anAttribute == YES"];
[request setPredicate:pred];
error = nil;
[_moc performBlockAndWait:^{
myStuff = [_moc executeFetchRequest:request error:&error];
}];
[request release];
if (error) {
NSLog(@"Error while fetching:\n%@",
([error localizedDescription] != nil) ?
[error localizedDescription] : @"Unknown Error");
return [NSArray array];
}
return myStuff;
}
返回iOS10上的ID数组和iOS9上的托管对象数组。
iOS9结果po myStuff
:
<_PFArray 0x16589ee0>(
<MyObj: 0x16589bb0> (
entity: myobs;
id: 0xd000000000040000 <x-coredata://81E85B5C-6504-4269-974B-5AB4449658DC/myobs/p1> ;
data: <fault>))
iOS10结果po myStuff
:
<__NSArrayM 0x170053e90>(
0xd000000000040000 <x-coredata://81E85B5C-6504-4269-974B-5AB4449658DC/myobs/p1>
)
为什么?
在iOS 10上,我可以通过调用
来检索对象[moc objectWithID:]
我在这里缺少什么?
答案 0 :(得分:0)
好的我明白了!导致此问题的核心数据行为发生了变化。它甚至记录在Apple's What's new In CoreData:
中performBlockAndWait :隐式包含每个块周围的自动释放池。使用ARC或Swift的项目通常应该不受影响,但要记住NSError **输出参数和异常都是自动释放的,并且不能快乐地逃避阻止词法范围。使用手动保留/释放的项目需要保留自动释放的对象,包括executeFetchRequest的结果:error:在块内部并释放或自动释放它们在块的词法范围之外。
... Jaix
因此解决方案是在通过performBlockAndWait
获取时保留并释放结果数组:
/* ... */
__block NSArray *result;
/* ... */
[moc performBlockAndWait:^{
result = [[moc executeFetchRequest:request error:&error] retain];
}];
/* ... */
return [result autorelease];
奇怪的是,文档说明了
Core Data已针对使用[..] iOS 10.0 [..]的最小部署目标构建的应用程序更改了两种行为。
我的IPHONEOS_DEPLOYMENT_TARGET
仍然设置为 6.0 ,所以我认为不是这样。
但是,我尝试使用从Xcode7链接的旧版 iPhoneOS9.2.sdk 进行构建。
只需将较旧的SDK链接到Xcode文件夹(并更新Info.plist中的MinimumSDKVersion
),即使我在 10.1 上保留了BaseSDK项目设置,该错误也会消失。
我在视图控制器(带按钮;))中隔离了这个问题,如下所示:
#import <CoreData/CoreData.h>
#import "ViewController.h"
//------------------------------- Data entries. --------------------------------
@interface MyObj : NSManagedObject {}
@property (nonatomic, retain) NSNumber *attribute;
@end
@implementation MyObj
@dynamic attribute;
@end
//----------------------------- View controller. -------------------------------
@interface ViewController () {
NSOperationQueue *m_q;
NSURL *m_dataURL;
NSManagedObjectModel *m_model;
NSPersistentStoreCoordinator *m_store;
}
@end
@implementation ViewController
- (void) viewDidLoad
{
[super viewDidLoad];
m_q = [[NSOperationQueue alloc] init];
m_dataURL = [[[[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask]
lastObject]
URLByAppendingPathComponent:@"mydata"]
retain];
m_model = [[self _createModel] retain];
m_store = [[self _createStore:m_model] retain];
}
- (void) dealloc
{
[m_q release];
[m_dataURL release];
[m_model release];
[m_store release];
[super dealloc];
}
- (void) refreshUI
{
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(refreshUI)
withObject:nil
waitUntilDone:NO];
return;
}
[self _loadData];
}
- (IBAction) buttonClicked:(id)sender
{
NSBlockOperation *create;
NSInvocationOperation *refresh;
create = [[NSBlockOperation alloc] init];
[create addExecutionBlock:^{
[self _createAndSaveData];
}];
refresh = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(refreshUI)
object:nil];
[refresh addDependency:create];
[m_q addOperation:create];
[m_q addOperation:refresh];
[create release];
[refresh release];
}
//--------------------------- Simple model. ------------------------------------
- (NSManagedObjectModel *)_createModel
{
NSManagedObjectModel *model;
NSEntityDescription *entity;
NSMutableArray *properties;
NSAttributeDescription *attribute;
properties = [[NSMutableArray alloc] init];
entity = [[NSEntityDescription alloc] init];
[entity setName:@"myobj"];
[entity setManagedObjectClassName:@"MyObj"];
attribute = [[NSAttributeDescription alloc] init];
[attribute setName:@"attribute"];
[attribute setAttributeType:NSInteger32AttributeType];
[properties addObject:attribute];
[attribute release];
[entity setProperties:properties];
[properties release];
model = [[NSManagedObjectModel alloc] init];
[model setEntities:@[entity]];
[entity release];
return [model autorelease];
}
- (NSPersistentStoreCoordinator *)_createStore:(NSManagedObjectModel *)model
{
NSPersistentStoreCoordinator *coordinator;
NSError *error;
NSPersistentStore *store;
error = nil;
coordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:model];
store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:m_dataURL
options:nil
error:&error];
if (!store) {
[coordinator release];
abort();
}
return [coordinator autorelease];
}
- (NSManagedObjectContext *)createContext:
(NSManagedObjectContextConcurrencyType)type
{
NSManagedObjectContext *ctx;
ctx = [[NSManagedObjectContext alloc] initWithConcurrencyType:type];
[ctx performBlockAndWait:^{
[ctx setPersistentStoreCoordinator:m_store];
}];
return [ctx autorelease];
}
//----------------------------- Data actions. ----------------------------------
- (void) _createAndSaveData
{
NSManagedObjectContext *moc;
moc = [self createContext:NSPrivateQueueConcurrencyType];
[moc performBlockAndWait:^{
MyObj *obj;
obj = [[MyObj alloc]
initWithEntity:[[m_model entitiesByName] objectForKey:@"myobj"]
insertIntoManagedObjectContext:moc];
[obj setAttribute:
[NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]];
[moc save:nil];
[obj release];
}];
}
- (NSArray *)_loadData
{
NSManagedObjectContext *moc;
NSFetchRequest *request;
__block NSError *error;
__block NSArray *objs;
moc = [self createContext:NSMainQueueConcurrencyType];
request = [[NSFetchRequest alloc] initWithEntityName:@"myobj"];
error = nil;
[moc performBlockAndWait:^{
// Retain here because of new autorelease pool!
objs = [[moc executeFetchRequest:request error:&error] retain];
}];
[request release];
if (error) {
return [NSArray array];
}
return [objs autorelease];
}
@end