Ios RACScheduler在NSManagedObject上的EXC_BAD_ACCESS KERN_INVALID_地址发生崩溃

Ios RACScheduler在NSManagedObject上的EXC_BAD_ACCESS KERN_INVALID_地址发生崩溃,ios,objective-c,core-data,reactive-cocoa,Ios,Objective C,Core Data,Reactive Cocoa,使用ReactiveCocoa 2.5,我们的应用程序中出现了一个反复出现、难以重现的崩溃 我们有一个后台调度程序,在应用程序的实时运行期间保留它。每当我们进行网络调用(使用AFNetworking)时,我们都会在这个后台调度程序上交付结果(大多数情况下都是JSON数据)。然后,我们将数据存储在后台核心数据上下文中,以最终在原始调度器(实际上是主调度器)上交付完成 此代码流的一个示例: - (RACSignal *)example { NSString *path = _applicat

使用ReactiveCocoa 2.5,我们的应用程序中出现了一个反复出现、难以重现的崩溃

我们有一个后台调度程序,在应用程序的实时运行期间保留它。每当我们进行网络调用(使用AFNetworking)时,我们都会在这个后台调度程序上交付结果(大多数情况下都是JSON数据)。然后,我们将数据存储在后台核心数据上下文中,以最终在原始调度器(实际上是主调度器)上交付完成

此代码流的一个示例:

- (RACSignal *)example {
    NSString *path = _applicationConfiguration.competitionsPath;

    @weakify(self)
    RACSignal *networkCallSignal = [[RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
        @strongify(self)
        NSURLSessionDataTask *task = [self _GETDataTaskWithSubscriber:subscriber path:path parameters:nil];
        return [RACDisposable disposableWithBlock:^{
            [task cancel];
        }];
    }] deliverOn:_backgroundScheduler];


    RACSignal *networkCallSignalToCoreDataSaveSignal = [[networkCallSignal flattenMap:^RACStream *(id result) {
        @strongify(self)
        NSError *error;
        Team *team = [self _saveJSONToCoreData:result error:&error];

        if (team) {
            return [RACSignal return:team.identifier];
        } else {
            return [RACSignal error:error];
        }
    }] subscribeOn:_backgroundScheduler];

    return [networkCallSignalToCoreDataSaveSignal deliverOn:[RACScheduler currentScheduler]];
}

- (Team *)_saveJSONToCoreData:(NSDictionary *)JSONData error:(NSError **)error {
    //naive implementation, for the sake of this example

    NSManagedObjectContext *context = ...;//context creation ommited for this example,
    NSEntityDescription *ed = [NSEntityDescription entityForName:@"Team" inManagedObjectContext:context];
    Team *team = [[Team alloc] initWithEntity:ed insertIntoManagedObjectContext:context];
    //setting properties on team from json dictionary here
    if ([context save:error]) {
        return team;
    } else {
        return nil;
    }
}

static id _afSessionManager;
- (NSURLSessionDataTask *)_GETDataTaskWithSubscriber:(id <RACSubscriber>)subscriber path:(NSString *)path parameters:(NSDictionary *)parameters {
    return [_afSessionManager GET:path parameters:parameters success:[self _succesBlock:subscriber path:path] failure:[self _failBlock:subscriber path:path]];
}

- (void (^)(NSURLSessionDataTask *, NSError *))_failBlock:(id <RACSubscriber>)subscriber path:(NSString *)path {
    return ^(NSURLSessionDataTask *t, NSError *error) {
        [subscriber sendError:error];
    };
}

- (void (^)(NSURLSessionDataTask *, id))_succesBlock:(id <RACSubscriber>)subscriber path:(NSString *)path {
    void (^success)(NSURLSessionDataTask *, id) = ^(NSURLSessionDataTask *t, id result) {
        [subscriber sendNext:result];
        [subscriber sendCompleted];
    };
    return success;
}    
正如您在下面的崩溃日志中所看到的,问题似乎是NSManagedObject的发布。这种情况偶尔发生,因此很难再现,但总是使用相同的堆栈跟踪

完整地说,下面是一个典型的崩溃日志:

Thread : Crashed: background.scheduler
0  libobjc.A.dylib                0x0000000196b17bd0 objc_msgSend + 16
1  CoreData                       0x0000000184fa6a00 -[NSManagedObject release] + 160
2  CoreData                       0x0000000184f9c490 -[_PFArray dealloc] + 100
3  libobjc.A.dylib                0x0000000196b1d724 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 564
4  exampleapp                     0x00000001000c0ec8 -[RACScheduler performAsCurrentScheduler:] (RACScheduler.m:203)
5  libdispatch.dylib              0x0000000197155994 _dispatch_call_block_and_release + 24
6  libdispatch.dylib              0x0000000197155954 _dispatch_client_callout + 16
7  libdispatch.dylib              0x00000001971600a4 _dispatch_queue_drain + 1448
8  libdispatch.dylib              0x0000000197158a5c _dispatch_queue_invoke + 132
9  libdispatch.dylib              0x0000000197162318 _dispatch_root_queue_drain + 720
10 libdispatch.dylib              0x0000000197163c4c _dispatch_worker_thread3 + 108
11 libsystem_pthread.dylib        0x000000019733522c _pthread_wqthread + 816
12 libsystem_pthread.dylib        0x0000000197334ef0 start_wqthread + 4
是否块周围的自动释放池会释放一个已经发布的NSManagedObject


有什么想法吗?

你在这方面运气好吗?我正在调查
-(rac*)setKeyPath:(NSString*)keyPath onObject:(NSObject*)object nilValue:(id)nilValue我怀疑这些可能是相关的。我们代码中的真正问题是在线程(/scheduler)之外使用的核心数据上下文。基本上,我们对所有核心数据代码进行了重构,以避免此类错误。在那之后,我们再也看不到这次坠机了。对不起,我不能再帮你了。
Thread : Crashed: background.scheduler
0  libobjc.A.dylib                0x0000000196b17bd0 objc_msgSend + 16
1  CoreData                       0x0000000184fa6a00 -[NSManagedObject release] + 160
2  CoreData                       0x0000000184f9c490 -[_PFArray dealloc] + 100
3  libobjc.A.dylib                0x0000000196b1d724 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 564
4  exampleapp                     0x00000001000c0ec8 -[RACScheduler performAsCurrentScheduler:] (RACScheduler.m:203)
5  libdispatch.dylib              0x0000000197155994 _dispatch_call_block_and_release + 24
6  libdispatch.dylib              0x0000000197155954 _dispatch_client_callout + 16
7  libdispatch.dylib              0x00000001971600a4 _dispatch_queue_drain + 1448
8  libdispatch.dylib              0x0000000197158a5c _dispatch_queue_invoke + 132
9  libdispatch.dylib              0x0000000197162318 _dispatch_root_queue_drain + 720
10 libdispatch.dylib              0x0000000197163c4c _dispatch_worker_thread3 + 108
11 libsystem_pthread.dylib        0x000000019733522c _pthread_wqthread + 816
12 libsystem_pthread.dylib        0x0000000197334ef0 start_wqthread + 4