簡體   English   中英

當UITextView滾動時NSTimer不觸發

[英]NSTimer not firing when UITextView is scrolling

我有一個UITextView,用於打印從文件中讀取的大量數據。 我將它放在NSTimer以便每秒100次輸入一行數據,將其打印到textView,然后播放數據並使用NSLog輸出一些內容。 但是,每當我滾動textView時,我都會注意到直到滾動完成,任何東西都不會通過NSLog輸出到控制台。

滾動條是否阻塞了主線程?

-(void) initialize{
    ...
    timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(hit:) userInfo:nil repeats:YES];
}

-(void)hit:(NSTimer*)time{
    double percentage = (double)lineIndex/(double)lines.count;
    //NSLog(@"%f", percentage);
    if (lineIndex < lines.count){
        [self recievedString:[lines objectAtIndex:lineIndex]];
        lineIndex += 1;
    }else{
        [time invalidate];
        timer = nil;
        [self.delegate finished];
    }
}

-(void)recievedString:(NSString *)line{
    NSArray *pieces = [line componentsSeparatedByString:@","];
    double accZ = [pieces[0] doubleValue];
    double accMag = [pieces[1] doubleValue];
    double gyroX = [pieces[2] doubleValue];
    double gyroZ = [pieces[3] doubleValue];
    [self crunchDatawithAccZ:accZ andAccMag:accMag andGyroX:gyroX andGyroZ:gyroZ];
}

-(void)crunchDatawithAccZ:(double)accZ andAccMag:(double)accMag andGyroX:(double)gyroX andGyroZ:(double)gyroZ {
    accMag = accMag*ACC_SENSITIVITY/(pow(2,DATA_WIDTH-1));
    accZ = accZ*ACC_SENSITIVITY/(pow(2,DATA_WIDTH-1));
    gyroX = gyroX*GYRO_SENSITIVITY/(pow(2,DATA_WIDTH-1));
    gyroZ = gyroZ*GYRO_SENSITIVITY/(pow(2,DATA_WIDTH-1));

    NSLog(@"%f, %f, %f, %f\n", accZ, accMag, gyroX, gyroZ);
    [self.delegate didReceiveData:[NSString stringWithFormat:@"%f, %f, %f, %f\n", accZ, accMag, gyroX, gyroZ]];

    [gyroX_array addObject:@(fabs(gyroX))];
...
}

委托方法:

-(void)didReceiveData:(NSString *)line{
    self.console.text = [self.console.text stringByAppendingFormat:@"\n%@", line];
    [self.console setContentOffset:CGPointMake(0, self.console.contentSize.height) animated:YES];
}

如果您檢查方法的文檔

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

它說(我強調了運行循環模式):

創建並返回一個新的NSTimer對象,並將其安排在默認模式下的當前運行循環中。 經過幾秒鍾后,計時器觸發,將消息aSelector發送到目標。

當iOS跟蹤觸摸事件時,主運行循環在UITrackingRunLoopMode中運行。 根據您的代碼的計時器在NSDefaultRunLoopMode中注冊(也就是,主運行循環不會退出繁忙狀態,可能只是空閑或正在等待事件。)。 因此,在UITrackingRunLoopMode中,runloop忙於使UIKit響應盡可能平滑。

要解決此問題,您需要在NSRunLoopCommonModes中注冊計時器(該值受所有運行循環模式監控)。

這是我認為對您有幫助的文檔摘錄:

計時器與您的運行循環的特定模式相關聯。 如果計時器不在運行循環當前正在監視的模式下,則在您以計時器支持的一種模式運行運行循環之前,它不會觸發。

如果您不熟悉runloop,請檢查此文檔

UIScrollView (或任何類似UITextView派生類)將在滾動時阻止主線程,以保持渲染流暢。 這使您的自定義計時器暫停。

要繞過這一點,一種簡單的方法是將其添加到模式為NSRunLoopCommonModes的主運行循環中:

timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(hit:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM