2016-08-25 37 views
0

考慮下面的代碼兩次:崩潰調用dispatch_source_create()時連續

@interface ViewController() 
@property (nonatomic, strong) dispatch_source_t source; 
@end 

@implementation ViewController 

-(void)viewDidLoad { 
    [super viewDidLoad]; 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 
    self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 
    dispatch_resume(self.source); 
    dispatch_source_set_timer(self.source, dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), 0.2 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC); 
    dispatch_source_set_event_handler(self.source, ^{ 
     NSLog(@"%s",__func__); 
    }); 
} 

@end 

如果我使用dispatch_source_create創建同樣DISPATCH_SOURCE_TYPE_TIMER兩次,應用程序會崩潰。爲什麼?

在上面的例子中創建一次和兩次調度源之間是否有區別?

libdispatch.dylib`_dispatch_xref_dispose: 
    0x10015e174 <+0>: ldr w8, [x0, #48] 
    0x10015e178 <+4>: cmp w8, #2     ; =2 
    0x10015e17c <+8>: b.hs 0x10015e184    ; <+16> 
    0x10015e180 <+12>: ret  
    0x10015e184 <+16>: stp x20, x21, [sp, #-16]! 
    0x10015e188 <+20>: adrp x20, 41 
    0x10015e18c <+24>: add x20, x20, #3849   ; =3849 
    0x10015e190 <+28>: adrp x21, 46 
    0x10015e194 <+32>: add x21, x21, #2440   ; =2440 
    0x10015e198 <+36>: str x20, [x21] 
    0x10015e19c <+40>: ldp x20, x21, [sp], #16 
-> 0x10015e1a0 <+44>: brk #0x1 
+0

爲什麼要那樣做?當你將第二個賦值給同一個屬性時,第一個將被釋放, – Paulw11

+0

@ Paulw11我知道這是無意義的代碼,第一個將在分配第二個時釋放,但是然後我繼續第二個。方式會崩潰,我認爲它仍然會正常工作,但它確實如此! – Jimmy

+0

由於處理調度對象時發生崩潰,它看起來像是一個計時問題。 – Paulw11

回答

3

正如他們所說,一張圖片勝過千言萬語:

detailed info

基本上你釋放暫停派遣對象,這似乎是prohibited由CGD。

恢復第一定時器將使崩潰消失:

self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 
dispatch_resume(self.source); 
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 
dispatch_resume(self.source);