objective c - Intermittent Crash on KVO Notification -


here's what's going on: i've got singleton monitoring device's event store changes. have property called events i've wrapped in eventssignal racsignal.

_eventssignal = [racable(self.events) startwith:nil]; 

when application finishes launching, prompts user access calendars (standard approach) using requestaccesstoentitytype:completion:. completion block executes on background queue, dispatch main queue:

-(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];           }       });   }]; } 

the call [self refresh] loads new events event store, calls

[self didchangevalueforkey:@"events"]; 

at line, app crashes.

-[__nscfstring sourcetype]: unrecognized selector sent instance 0x200d6c80 

the full stack trace below. i've tried removing dispatch call, scheduling _eventsignal on main thread scheduler, , looking @ everywhere i'm subscribing event signal (it looks good). missing?

edit: i've isolate problem down following code. if nexteventsignal subscribed @ all, crash happens half time. if remove second signal combinelatest:reduce call, not crash.

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]; 

here's crash log.

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 @ 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 @ racstream.m:56 frame #23: 0x000f26a2 upcoming`+[racsignal(self=0x001ab424, _cmd=0x0012e129, value=0x1ed6dee0) return:] + 222 @ racsignal.m:165 frame #24: 0x000fa926 upcoming`__29-[racstream(.block_descriptor=0x1edf57b0, value=0x1ed52170) map:]_block_invoke + 86 @ racstream.m:91 frame #25: 0x000fa13c upcoming`__36-[racstream(.block_descriptor=0x200f3970, value=0x1ed52170, stop=0x2fdc1580) flattenmap:]_block_invoke_2 + 44 @ racstream.m:72 frame #26: 0x000f39f4 upcoming`__29-[racsignal(.block_descriptor=0x200f3b70, x=0x1ed52170) bind:]_block_invoke178 + 56 @ racsignal.m:243 frame #27: 0x000ffbb6 upcoming`-[racsubscriber sendnext:](self=0x200f3a90, _cmd=0x00124ec2, value=0x1ed52170) + 294 @ racsubscriber.m:69 frame #28: 0x000deb04 upcoming`__43-[racsignal(.block_descriptor=0x200f3cc0) combinelatestwith:]_block_invoke_2 + 304 @ racsignal+operations.m:462 frame #29: 0x000ded76 upcoming`__43-[racsignal(.block_descriptor=0x200f3df0, x=0x20196dc0) combinelatestwith:]_block_invoke463 + 282 @ racsignal+operations.m:469 frame #30: 0x000ffbb6 upcoming`-[racsubscriber sendnext:](self=0x200f3d30, _cmd=0x00124ec2, value=0x20196dc0) + 294 @ racsubscriber.m:69 frame #31: 0x000f3694 upcoming`__29-[racsignal(.block_descriptor=0x1eda3610, x=0x20196dc0) bind:]_block_invoke_2157 + 76 @ racsignal.m:222 frame #32: 0x000ffbb6 upcoming`-[racsubscriber sendnext:](self=0x1edea190, _cmd=0x00124ec2, value=0x20196dc0) + 294 @ racsubscriber.m:69 frame #33: 0x000f2746 upcoming`__31+[racsignal(.block_descriptor=0x1edc5dd0, subscriber=0x1edea190) return:]_block_invoke + 106 @ racsignal.m:166 frame #34: 0x000f6a30 upcoming`__37-[racsignal(.block_descriptor=0x2fdc1c20) subscribe:]_block_invoke300 + 80 @ racsignal.m:386 frame #35: 0x00100aca upcoming`-[racsubscriptionscheduler schedule:](self=0x200c0e00, _cmd=0x0012de2e, block=0x2fdc1c20) + 542 @ racsubscriptionscheduler.m:40 frame #36: 0x000f650c upcoming`-[racsignal(self=0x2019a790, _cmd=0x0012de00, subscriber=0x1edea190) subscribe:] + 1300 @ racsignal.m:388 frame #37: 0x000f74ec upcoming`-[racsignal(self=0x2019a790, _cmd=0x0012f167, nextblock=0x2fdc1ee4, errorblock=0x2fdc1ec8, completedblock=0x2fdc1ea8) subscribenext:error:completed:] + 1124 @ racsignal.m:419 frame #38: 0x000f3528 upcoming`__29-[racsignal(.block_descriptor=0x200f3fe0, signal=0x2019a790) bind:]_block_invoke154 + 636 @ racsignal.m:230 frame #39: 0x000f3a22 upcoming`__29-[racsignal(.block_descriptor=0x200f4130, x=0x200365e0) bind:]_block_invoke178 + 102 @ racsignal.m:246 frame #40: 0x000ffbb6 upcoming`-[racsubscriber sendnext:](self=0x200f4050, _cmd=0x00124ec2, value=0x200365e0) + 294 @ racsubscriber.m:69 frame #41: 0x000f3694 upcoming`__29-[racsignal(.block_descriptor=0x1ed08f40, x=0x200365e0) bind:]_block_invoke_2157 + 76 @ racsignal.m:222 frame #42: 0x000ffbb6 upcoming`-[racsubscriber sendnext:](self=0x1ed077b0, _cmd=0x00124ec2, value=0x200365e0) + 294 @ racsubscriber.m:69 frame #43: 0x000f2746 upcoming`__31+[racsignal(.block_descriptor=0x202adf90, subscriber=0x1ed077b0) return:]_block_invoke + 106 @ racsignal.m:166 frame #44: 0x000f6a30 upcoming`__37-[racsignal(.block_descriptor=0x2fdc23c0) subscribe:]_block_invoke300 + 80 @ racsignal.m:386 frame #45: 0x00100aca upcoming`-[racsubscriptionscheduler schedule:](self=0x200c0e00, _cmd=0x0012de2e, block=0x2fdc23c0) + 542 @ racsubscriptionscheduler.m:40 frame #46: 0x000f650c upcoming`-[racsignal(self=0x20021f60, _cmd=0x0012de00, subscriber=0x1ed077b0) subscribe:] + 1300 @ racsignal.m:388 frame #47: 0x000f74ec upcoming`-[racsignal(self=0x20021f60, _cmd=0x0012f167, nextblock=0x2fdc2684, errorblock=0x2fdc2668, completedblock=0x2fdc2648) subscribenext:error:completed:] + 1124 @ racsignal.m:419 frame #48: 0x000f3528 upcoming`__29-[racsignal(.block_descriptor=0x200f48e0, signal=0x20021f60) bind:]_block_invoke154 + 636 @ racsignal.m:230 frame #49: 0x000f3a22 upcoming`__29-[racsignal(.block_descriptor=0x200f4b40, x=0x200134a0) bind:]_block_invoke178 + 102 @ racsignal.m:246 frame #50: 0x000ffbb6 upcoming`-[racsubscriber sendnext:](self=0x200f4950, _cmd=0x00124ec2, value=0x200134a0) + 294 @ 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 @ 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 @ 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 @ ekeventmanager.m:216 frame #59: 0x000591ac upcoming`-[ekeventmanager refresh](self=0x200c2a80, _cmd=0x33e9fe1c) + 64 @ ekeventmanager.m:82 frame #60: 0x000590d6 upcoming`__33-[ekeventmanager promptforaccess]_block_invoke_2(.block_descriptor=0x2005d020) + 246 @ 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 @ main.m:15 frame #70: 0x3b83cb20 libdyld.dylib`start + 4 

the problem turned out holding onto references eventkit objects after resetting store. objects become "invalid" when store reset, guess means become dangling pointers (awesome). combinelatest:reduce: failing when first key changed because latest value on second signal invalid. sending nil both signals before resetting store seems 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 set these nil before resetting store.                 [self willchangevalueforkey:ekeventmanagereventskeypath];                 _events = nil;                 [self didchangevalueforkey:ekeventmanagereventskeypath];                 [self willchangevalueforkey:ekeventmanagernexteventkeypath];                 _nextevent = nil;                 [self didchangevalueforkey:ekeventmanagernexteventkeypath];                  // load events                 [_store reset];                 [self refresh];             }         });     }]; } 

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -