2010-04-26 25 views
8

Lưu ý: Có thể cuộn xuống để đọc bản chỉnh sửa của tôi.Đặt một NSTimer vào một chủ đề riêng biệt

Tôi đang cố gắng thiết lập một NSTimer trong một chuỗi riêng biệt để nó tiếp tục kích hoạt khi người dùng tương tác với giao diện người dùng của ứng dụng của tôi. Điều này dường như hoạt động, nhưng Rò rỉ báo cáo một số vấn đề - và tôi tin rằng tôi đã thu hẹp nó xuống mã bộ đếm thời gian của tôi.

Hiện tại điều đang xảy ra là updateTimer cố gắng truy cập vào NSArrayController (timersController) được liên kết với một NSTableView trong giao diện ứng dụng của tôi. Từ đó, tôi lấy hàng được chọn đầu tiên và thay đổi cột timeSpent của nó. Lưu ý: nội dung của timersController là một tập hợp các đối tượng được quản lý được tạo thông qua Core Data.

Từ đọc xung quanh, tôi tin rằng những gì tôi nên cố gắng làm là thực hiện chức năng updateTimer trên chủ đề chính, chứ không phải trong chủ đề thứ cấp của bộ tính giờ của tôi.

Tôi đăng bài ở đây với hy vọng rằng ai đó có nhiều kinh nghiệm hơn có thể cho tôi biết nếu đó là điều duy nhất tôi làm sai. Sau khi đọc tài liệu của Apple về Threading, tôi đã tìm thấy nó là một lĩnh vực chủ đề lớn.

NSThread *timerThread = [[[NSThread alloc] initWithTarget:self selector:@selector(startTimerThread) object:nil] autorelease]; 
[timerThread start]; 

-(void)startTimerThread 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
    activeTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES] retain]; 

    [runLoop run]; 
    [pool release]; 
} 
-(void)updateTimer:(NSTimer *)timer 
{ 
    NSArray *selectedTimers = [timersController selectedObjects]; 
    id selectedTimer = [selectedTimers objectAtIndex:0]; 
    NSNumber *currentTimeSpent = [selectedTimer timeSpent]; 

    [selectedTimer setValue:[NSNumber numberWithInt:[currentTimeSpent intValue]+1] forKey:@"timeSpent"]; 
} 
-(void)stopTimer 
{ 
    [activeTimer invalidate]; 
    [activeTimer release]; 
} 

CẬP NHẬT

tôi vẫn hoàn toàn mất liên quan đến rò rỉ này. Tôi biết tôi rõ ràng đang làm điều gì đó sai trái, nhưng tôi đã rút đơn của tôi xuống phần xương trần của nó và vẫn không thể tìm thấy nó. Vì mục đích đơn giản, tôi đã tải mã bộ điều khiển ứng dụng của mình lên: a small pastebin. Lưu ý rằng bây giờ tôi đã xóa mã chuỗi bộ hẹn giờ và thay vào đó đã chọn chạy bộ hẹn giờ trong một runloop riêng biệt (như được đề xuất ở đây).

Nếu tôi đặt Rò rỉ Gọi Tree để ẩn cả hai biểu tượng Thiếu và Thư viện System, Tôi nhìn thấy đầu ra sau đây:

EDIT: Liên kết đến ảnh chụp màn hình bị phá vỡ và do loại bỏ.

+0

Tại sao bạn thiết lập một vòng lặp chạy bổ sung? Bộ hẹn giờ của bạn có thể hoạt động bình thường với vòng lặp chạy chính. – zneak

+0

Liên kết ghi đè đã chết. –

Trả lời

51

Nếu lý do duy nhất bạn đang đẻ trứng một chủ đề mới là cho phép hẹn giờ của bạn để chạy khi người dùng đang tương tác với giao diện người dùng bạn chỉ có thể thêm nó vào chế độ runloop khác nhau:

NSTimer *uiTimer = [NSTimer timerWithTimeInterval:(1.0/5.0) target:self selector:@selector(uiTimerFired:) userInfo:nil repeats:YES];  
[[NSRunLoop mainRunLoop] addTimer:uiTimer forMode:NSRunLoopCommonModes]; 

Là một phụ lục câu trả lời này bây giờ có thể để sắp xếp giờ sử dụng Grand Central Dispatch và khối:

// Update the UI 5 times per second on the main queue 
// Keep a strong reference to _timer in ARC 
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); 
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, (1.0/5.0) * NSEC_PER_SEC, 0.25 * NSEC_PER_SEC); 

dispatch_source_set_event_handler(_timer, ^{ 
    // Perform a periodic action 
}); 

// Start the timer 
dispatch_resume(_timer); 

Sau này khi bộ đếm thời gian không còn cần thiết:

dispatch_source_cancel(_timer); 
+0

Đó là một giải pháp dễ dàng hơn nhiều, cảm ơn bạn. Tôi đã dành một chút thời gian đọc trên runloops. Thật không may, nó dường như không giúp đỡ với rò rỉ của tôi. Tôi đã thu hẹp nó xuống (tôi tin) một vấn đề trong hàm updateTimer. Tôi tin rằng nó có liên quan đến cách tôi cập nhật biến timeSpent trong NSArray của các đối tượng được quản lý. – ndg

+0

Nếu mã bạn đăng ở trên là hàm updateTimer thực tế của bạn, có vẻ như là OK. Bạn cần phải cẩn thận không để phát hành một bộ đếm thời gian một khi bạn đã vô hiệu hóa nó, mặc dù. – sbooth

+0

Đó thực sự là chức năng updateTimer thực tế của tôi.Tôi đã cập nhật OP để tóm tắt các vấn đề tôi thấy (và để cập nhật mã được sử dụng). – ndg

Các vấn đề liên quan