2010-06-09 27 views
5

Tôi đang chạy một mainloop trong Cocoa sử dụng một NSTimer thiết lập như thế này:Thay đổi NSTimer khoảng cho lặp lại timer

 mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/fps target:self selector:@selector(mainloop) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode]; 

Lúc khởi động Chương trình tôi đặt timeInterval đến 0.0 để các mainloop chạy càng nhanh càng tốt. Dù sao, tôi muốn cung cấp một chức năng để thiết lập tốc độ khung hình (và do đó khoảng thời gian của bộ đếm thời gian) đến một giá trị cụ thể khi chạy. Thật không may như xa như tôi biết đó có nghĩa là tôi phải khởi tạo lại bộ đếm thời gian kể từ Cocoa không cung cấp một chức năng như "setTimerInterval" Đây là những gì tôi đã cố gắng:

- (void)setFrameRate:(float)aFps 
{ 
    NSLog(@"setFrameRate"); 
    [mainLoopTimer invalidate]; 
    mainLoopTimer = nil; 

    mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/aFps target:self selector:@selector(mainloop) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode]; 
} 

nhưng điều này ném các lỗi sau và dừng mainloop :

2010-06-09 11: 14: 15,868 myTarget [7313: a0f] setFrameRate 2010/06/09 11: 14: 15,868 myTarget [7313: a0f] * __NSAutoreleaseNoPool(): Object 0x40cd80 của class __NSCFDate autoreleased không có pool tại chỗ - chỉ rò rỉ 2010-06-09 11: 14: 15.869 myTarget [7313: a0f] * __NSAutoreleaseNoPool(): Object 0x40e700 của lớp NSCFTimer autoreleased không có hồ bơi tại chỗ - chỉ rò rỉ 0,614628

Tôi cũng đã cố gắng để tái tạo bộ đếm thời gian bằng cách sử dụng "giữ lại" từ khóa, nhưng điều đó không thay đổi bất cứ điều gì. Bất kỳ ý tưởng nào về cách tự động thay đổi khoảng thời gian của một NSTimer trong thời gian chạy?

Cảm ơn!

Trả lời

0

Bạn không nên phát hành mainLoopTimer.
Khi bạn tạo nó, bạn đã nhận được một cá thể được tự động phát hành và runloop đang giữ tham chiếu đến cá thể đó.
Nó sẽ được phát hành khi bạn xóa nó khỏi vòng lặp: nếu bạn tự phát hành nó, nó sẽ bị xóa và runloop cố gắng truy cập một đối tượng không hợp lệ.
Đó là lý do tại sao nó bị treo.

EDIT: Tôi hoàn toàn bị đọc nhầm và tôi nghĩ rằng tôi đã thấy bản phát hành khi nó bị vô hiệu, xin lỗi. Vấn đề có vẻ là không có AutoreleasePool tại chỗ. Điều này thường được thực hiện trong main(): tạo ra các hồ bơi autorelease là điều đầu tiên

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

và phát hành nó chỉ trước khi thoát khỏi chính.

Có giao diện here cho tài liệu Tự động phát hành hồ bơi.

+0

tôi nên làm gì để thay đổi khoảng thời gian? – moka

+0

Tôi cầu xin sự tha thứ của bạn. Tôi đã đọc sai [mainLoopTimer release]. Bạn đang hoạt động chính xác với bộ hẹn giờ, nhưng dường như không có AutoReleasePool tại chỗ. có một cái nhìn ở đây: http://developer.apple.com/mac/library/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html – garph0

+0

hmm Tôi allready đã cố gắng để đặt một autoreleasepool tại chỗ, nhưng nó không hoạt động , nhưng tôi sẽ thử lại! – moka

-2

Bạn có thể thử hủy đăng ký hẹn giờ trước đó và bắt đầu hẹn giờ mới với tần suất khác nhau. bạn có thể hủy đăng ký theo số

[yourOldTimer invalidate]; 
yourOldTimer = nil; 

Điều này có thể giải quyết được mục đích.

+0

như bạn có thể thấy, đó là những gì tôi đã làm allready, và nó không hoạt động. – moka

3

Tôi biết, chủ đề này thật tuyệt vời! Nhưng tôi cũng đang tìm kiếm chức năng!

Khi nó bật ra, NSTimes không cung cấp tính năng này, tôi quyết định xây dựng một tính năng riêng. Nó không phải là giải pháp tốt nhất, nhưng trong trường hợp của tôi nó là chỉ có thể.

Tôi đã xác định biến "BOOL keepOn;" trong tiêu đề của tôi.

-(IBAction)doSomething:(id)sender 
{ 
    // Any action to throw every interval. 
} 

-(IBAction)switchAutoLoad:(id)sender 
{ 
    if([autoLoad state] == NSOffState) 
    { 
     NSLog(@"auto-reload on!"); 

     self performSelector:@selector(fireTimer) withObject:nil afterDelay:0]; 
     keepOn = YES; 
     [autoLoad setState:NSOnState]; 
    } 
    else 
    { 
     NSLog(@"auto-reload off!"); 
     keepOn = NO; 
     [autoLoad setState:NSOffState]; 
    } 
} 

-(void)fireTimer 
{ 
    [self doSomething:nil]; 

    float theTime = 20; // This is the time interval. 

    if(keepOn) 
    { 
     [self performSelector:@selector(fireTimer) withObject:nil afterDelay:theTime]; 
    } 
} 

Vấn đề (rất) là "hẹn giờ" đang chờ đợi toàn bộ thời gian trễ trước khi có thể nhận được giá trị mới. Bạn thấy đấy, nó không phản hồi nhanh :)) Và bạn không thể dừng nó ngay lập tức (phải đợi cho đến khi kết thúc trễ).

Và nếu bạn dừng nó, nó sẽ ném thêm một hành động như được cho là.

Thực ra nó hoạt động cho tôi và không sao cho các ứng dụng và công cụ nhỏ.

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