1

这是发生了什么:我有一个单例监视设备的事件存储以进行更改。我有一个名为的属性events,我用eventsSignal RACSignal.

_eventsSignal = [RACAble(self.events) startWith:nil];

当应用程序完成启动时,它会提示用户使用requestAccessToEntityType:completion:. 完成块在后台队列上执行,所以我调度回主队列:

-(void)promptForAccess {
  [_store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
      dispatch_async(dispatch_get_main_queue(), ^{
          [self willChangeValueForKey:EKEventManagerAccessibleKeyPath];
          _accessible = granted;
          [self didChangeValueForKey:EKEventManagerAccessibleKeyPath];

          if (_accessible) {
              // load events
              [_store reset];
              [self refresh];
          }
      });
  }];
}

[self refresh]从事件存储中加载新事件的调用,然后调用

[self didChangeValueForKey:@"events"];

在这一行,应用程序崩溃。

-[__NSCFString sourceType]: unrecognized selector sent to instance 0x200d6c80

完整的堆栈跟踪如下。我已经尝试删除调度调用,总是_eventSignal在主线程调度程序上调度,并查看我订阅事件信号的所有地方(看起来都不错)。有什么我可能会丢失的吗?

编辑:我已将问题隔离在以下代码中。如果nextEventSignal订阅了 ,那么崩溃发生的时间大约有一半。如果我从通话中删除第二个信号combineLatest:reduce,那么它不会崩溃。

RACSignal *nextEventSignal = [[RACSignal combineLatest:@[eventManager.eventsSignal, eventManager.nextEventSignal, timerSignal] reduce:^id (NSArray *eventArray, EKEvent *nextEvent, NSDate *fireDate){
    NSArray *filteredArray = [[eventArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL (EKEvent *event, NSDictionary *bindings) {
        return [event.endDate isLaterThanDate:[NSDate date]] && !event.isAllDay;
    }]] sortedArrayUsingComparator:^NSComparisonResult (id obj1, id obj2) {
        return [[obj1 startDate] compare:[obj2 startDate]];
    }];

    if (filteredArray.count == 0) {
        if (nextEvent.isAllDay) {
            return  nil;
        }
        else {
            return nextEvent;
        }
    } else {
        return filteredArray[0];
    }
}] throttle:0.25f];

这是崩溃日志。

thread #1: tid = 0x2503, 0x3b40f944 libobjc.A.dylib`objc_exception_throw, stop reason = breakpoint 2.1
frame #0: 0x3b40f944 libobjc.A.dylib`objc_exception_throw
frame #1: 0x33717f30 CoreFoundation`-[NSObject(NSObject) doesNotRecognizeSelector:] + 184
frame #2: 0x3371664c CoreFoundation`___forwarding___ + 392
frame #3: 0x3366e208 CoreFoundation`__forwarding_prep_0___ + 24
frame #4: 0x33e0442c EventKit`-[EKCalendar type] + 68
frame #5: 0x33e49e10 EventKit`-[EKCalendar description] + 84
frame #6: 0x33f7d204 Foundation`_NSDescriptionWithLocaleFunc + 88
frame #7: 0x336f5430 CoreFoundation`__CFStringAppendFormatCore + 11160
frame #8: 0x3366c8a2 CoreFoundation`_CFStringCreateWithFormatAndArgumentsAux + 74
frame #9: 0x33f7ccfc Foundation`+[NSString stringWithFormat:] + 60
frame #10: 0x33e5427c EventKit`-[EKCalendarItem description] + 228
frame #11: 0x33e4ccae EventKit`-[EKEvent description] + 46
frame #12: 0x336a35d0 CoreFoundation`-[NSArray descriptionWithLocale:indent:] + 680
frame #13: 0x33f7d1f0 Foundation`_NSDescriptionWithLocaleFunc + 68
frame #14: 0x336f5430 CoreFoundation`__CFStringAppendFormatCore + 11160
frame #15: 0x3366c8a2 CoreFoundation`_CFStringCreateWithFormatAndArgumentsAux + 74
frame #16: 0x33f7ccfc Foundation`+[NSString stringWithFormat:] + 60
frame #17: 0x0010102a Upcoming`-[RACTuple description](self=0x1ed6dee0, _cmd=0x391cb2ce) + 182 at RACTuple.m:62
frame #18: 0x33f7d204 Foundation`_NSDescriptionWithLocaleFunc + 88
frame #19: 0x336f5430 CoreFoundation`__CFStringAppendFormatCore + 11160
frame #20: 0x3366c8a2 CoreFoundation`_CFStringCreateWithFormatAndArgumentsAux + 74
frame #21: 0x33f873de Foundation`-[NSString initWithFormat:arguments:] + 26
frame #22: 0x000f9e50 Upcoming`-[RACStream setNameWithFormat:](self=0x1eda2a70, _cmd=0x0012e18b, format=0x001ad984) + 436 at RACStream.m:56
frame #23: 0x000f26a2 Upcoming`+[RACSignal(self=0x001ab424, _cmd=0x0012e129, value=0x1ed6dee0) return:] + 222 at RACSignal.m:165
frame #24: 0x000fa926 Upcoming`__29-[RACStream(.block_descriptor=0x1edf57b0, value=0x1ed52170) map:]_block_invoke + 86 at RACStream.m:91
frame #25: 0x000fa13c Upcoming`__36-[RACStream(.block_descriptor=0x200f3970, value=0x1ed52170, stop=0x2fdc1580) flattenMap:]_block_invoke_2 + 44 at RACStream.m:72
frame #26: 0x000f39f4 Upcoming`__29-[RACSignal(.block_descriptor=0x200f3b70, x=0x1ed52170) bind:]_block_invoke178 + 56 at RACSignal.m:243
frame #27: 0x000ffbb6 Upcoming`-[RACSubscriber sendNext:](self=0x200f3a90, _cmd=0x00124ec2, value=0x1ed52170) + 294 at RACSubscriber.m:69
frame #28: 0x000deb04 Upcoming`__43-[RACSignal(.block_descriptor=0x200f3cc0) combineLatestWith:]_block_invoke_2 + 304 at RACSignal+Operations.m:462
frame #29: 0x000ded76 Upcoming`__43-[RACSignal(.block_descriptor=0x200f3df0, x=0x20196dc0) combineLatestWith:]_block_invoke463 + 282 at RACSignal+Operations.m:469
frame #30: 0x000ffbb6 Upcoming`-[RACSubscriber sendNext:](self=0x200f3d30, _cmd=0x00124ec2, value=0x20196dc0) + 294 at RACSubscriber.m:69
frame #31: 0x000f3694 Upcoming`__29-[RACSignal(.block_descriptor=0x1eda3610, x=0x20196dc0) bind:]_block_invoke_2157 + 76 at RACSignal.m:222
frame #32: 0x000ffbb6 Upcoming`-[RACSubscriber sendNext:](self=0x1edea190, _cmd=0x00124ec2, value=0x20196dc0) + 294 at RACSubscriber.m:69
frame #33: 0x000f2746 Upcoming`__31+[RACSignal(.block_descriptor=0x1edc5dd0, subscriber=0x1edea190) return:]_block_invoke + 106 at RACSignal.m:166
frame #34: 0x000f6a30 Upcoming`__37-[RACSignal(.block_descriptor=0x2fdc1c20) subscribe:]_block_invoke300 + 80 at RACSignal.m:386
frame #35: 0x00100aca Upcoming`-[RACSubscriptionScheduler schedule:](self=0x200c0e00, _cmd=0x0012de2e, block=0x2fdc1c20) + 542 at RACSubscriptionScheduler.m:40
frame #36: 0x000f650c Upcoming`-[RACSignal(self=0x2019a790, _cmd=0x0012de00, subscriber=0x1edea190) subscribe:] + 1300 at RACSignal.m:388
frame #37: 0x000f74ec Upcoming`-[RACSignal(self=0x2019a790, _cmd=0x0012f167, nextBlock=0x2fdc1ee4, errorBlock=0x2fdc1ec8, completedBlock=0x2fdc1ea8) subscribeNext:error:completed:] + 1124 at RACSignal.m:419
frame #38: 0x000f3528 Upcoming`__29-[RACSignal(.block_descriptor=0x200f3fe0, signal=0x2019a790) bind:]_block_invoke154 + 636 at RACSignal.m:230
frame #39: 0x000f3a22 Upcoming`__29-[RACSignal(.block_descriptor=0x200f4130, x=0x200365e0) bind:]_block_invoke178 + 102 at RACSignal.m:246
frame #40: 0x000ffbb6 Upcoming`-[RACSubscriber sendNext:](self=0x200f4050, _cmd=0x00124ec2, value=0x200365e0) + 294 at RACSubscriber.m:69
frame #41: 0x000f3694 Upcoming`__29-[RACSignal(.block_descriptor=0x1ed08f40, x=0x200365e0) bind:]_block_invoke_2157 + 76 at RACSignal.m:222
frame #42: 0x000ffbb6 Upcoming`-[RACSubscriber sendNext:](self=0x1ed077b0, _cmd=0x00124ec2, value=0x200365e0) + 294 at RACSubscriber.m:69
frame #43: 0x000f2746 Upcoming`__31+[RACSignal(.block_descriptor=0x202adf90, subscriber=0x1ed077b0) return:]_block_invoke + 106 at RACSignal.m:166
frame #44: 0x000f6a30 Upcoming`__37-[RACSignal(.block_descriptor=0x2fdc23c0) subscribe:]_block_invoke300 + 80 at RACSignal.m:386
frame #45: 0x00100aca Upcoming`-[RACSubscriptionScheduler schedule:](self=0x200c0e00, _cmd=0x0012de2e, block=0x2fdc23c0) + 542 at RACSubscriptionScheduler.m:40
frame #46: 0x000f650c Upcoming`-[RACSignal(self=0x20021f60, _cmd=0x0012de00, subscriber=0x1ed077b0) subscribe:] + 1300 at RACSignal.m:388
frame #47: 0x000f74ec Upcoming`-[RACSignal(self=0x20021f60, _cmd=0x0012f167, nextBlock=0x2fdc2684, errorBlock=0x2fdc2668, completedBlock=0x2fdc2648) subscribeNext:error:completed:] + 1124 at RACSignal.m:419
frame #48: 0x000f3528 Upcoming`__29-[RACSignal(.block_descriptor=0x200f48e0, signal=0x20021f60) bind:]_block_invoke154 + 636 at RACSignal.m:230
frame #49: 0x000f3a22 Upcoming`__29-[RACSignal(.block_descriptor=0x200f4b40, x=0x200134a0) bind:]_block_invoke178 + 102 at RACSignal.m:246
frame #50: 0x000ffbb6 Upcoming`-[RACSubscriber sendNext:](self=0x200f4950, _cmd=0x00124ec2, value=0x200134a0) + 294 at RACSubscriber.m:69
frame #51: 0x000b8e98 Upcoming`__86+[NSObject(.block_descriptor=0x200f4db0, target=0x200c2a80, observer=0x200c2a80, change=0x200134a0) rac_signalWithChangesFor:keyPath:options:observer:]_block_invoke_2 + 96 at NSObject+RACPropertySubscribing.m:55
frame #52: 0x000c8d46 Upcoming`-[RACKVOTrampoline observeValueForKeyPath:ofObject:change:context:](self=0x200f4d90, _cmd=0x359cf919, keyPath=0x200c9340, object=0x200c2a80, change=0x200134a0, context=0x001b4444) + 542 at RACKVOTrampoline.m:97
frame #53: 0x340095f2 Foundation`NSKVONotify + 34
frame #54: 0x34007b46 Foundation`-[NSKeyValueObservance observeValueForKeyPath:ofObject:change:context:] + 310
frame #55: 0x33fa3b84 Foundation`NSKeyValueNotifyObserver + 272
frame #56: 0x33fa37dc Foundation`NSKeyValueDidChange + 336
frame #57: 0x33f7dcba Foundation`-[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 94
frame #58: 0x0005a732 Upcoming`-[EKEventManager loadEvents](self=0x200c2a80, _cmd=0x00126d19) + 2834 at EKEventManager.m:216
frame #59: 0x000591ac Upcoming`-[EKEventManager refresh](self=0x200c2a80, _cmd=0x33e9fe1c) + 64 at EKEventManager.m:82
frame #60: 0x000590d6 Upcoming`__33-[EKEventManager promptForAccess]_block_invoke_2(.block_descriptor=0x2005d020) + 246 at EKEventManager.m:74
frame #61: 0x3b829792 libdispatch.dylib`_dispatch_call_block_and_release + 10
frame #62: 0x3b8295da libdispatch.dylib`_dispatch_client_callout + 22
frame #63: 0x3b82ce44 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 228
frame #64: 0x336e81b0 CoreFoundation`__CFRunLoopRun + 1288
frame #65: 0x3365b23c CoreFoundation`CFRunLoopRunSpecific + 356
frame #66: 0x3365b0c8 CoreFoundation`CFRunLoopRunInMode + 104
frame #67: 0x3723a33a GraphicsServices`GSEventRunModal + 74
frame #68: 0x355772b8 UIKit`UIApplicationMain + 1120
frame #69: 0x0003e074 Upcoming`main(argc=1, argv=0x2fdc3d20) + 116 at main.m:15
frame #70: 0x3b83cb20 libdyld.dylib`start + 4
4

1 回答 1

1

The problem turned out to be that I was holding onto references to EventKit objects after resetting the store. The objects become "invalid" when the store is reset, which I guess means they become dangling pointers (awesome). The combineLatest:reduce: was failing when the first key changed because the latest value on the second signal was invalid. Sending nil to both signals just before resetting the store seems to have worked.

-(void)promptForAccess {
    [_store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self willChangeValueForKey:EKEventManagerAccessibleKeyPath];
            _accessible = granted;
            [self didChangeValueForKey:EKEventManagerAccessibleKeyPath];

            if (_accessible) {
                // need to set these to nil before resetting the store.
                [self willChangeValueForKey:EKEventManagerEventsKeyPath];
                _events = nil;
                [self didChangeValueForKey:EKEventManagerEventsKeyPath];
                [self willChangeValueForKey:EKEventManagerNextEventKeyPath];
                _nextEvent = nil;
                [self didChangeValueForKey:EKEventManagerNextEventKeyPath];

                // load events
                [_store reset];
                [self refresh];
            }
        });
    }];
}
于 2013-05-14T18:08:44.677 回答