macOS循环执行期间支持用户输入的Objective-C开发问题咨询
你提出的批量创建NSTimer方案的缺陷
- 性能损耗过高:一次性创建10000个定时器实例并全部加入主运行循环,会产生大量不必要的内存占用和调度开销,总循环次数越大,性能损耗越明显。
- 执行逻辑不可控:所有定时器的触发时间均设置为0.1秒后,会出现大量定时器扎堆触发的情况,短时间内占用大量主线程资源容易引发UI掉帧,整体任务的执行时长也无法精准控制。
- 停止逻辑不彻底:设置
stopBatch = true后,已经加入调度队列的所有定时器依然会依次触发,只是执行时直接返回,这些无效调度依然会占用系统资源,不会主动被移除。 - 维护成本高:如果需要调整总执行次数、单步执行的步长,都需要同时修改定时器创建逻辑和
timerCalled内部的业务逻辑,后续迭代容易出现不兼容问题。
低改造成本的可选解决方案
方案1:主循环手动处理运行循环事件(改造成本最低)
仅需在原主线程循环逻辑中新增一行代码,手动让主运行循环处理一次用户输入等事件,无需拆分UI逻辑,改动量极小:
-(void) runMain{ stopBatch = false; [textData setStringValue:@"Start"]; [textData displayIfNeeded]; NSString * iString = @"0"; for (int i=0;i<=10000 ;i++) { if(stopBatch) break; iString= [NSString stringWithFormat: @"%d",i]; [textData setStringValue:iString]; [textData displayIfNeeded]; // 手动处理当前队列中的所有事件,处理完成立刻返回,无多余等待 [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]; } }
方案2:单个重复定时器方案
仅创建一个重复定时器替代批量创建定时器,性能开销更低,停止逻辑更彻底:
// 新增类属性 @property (nonatomic, assign) NSInteger iVal; @property (nonatomic, strong) NSTimer *batchTimer; -(void) runMain{ stopBatch = false; self.iVal = 0; // 仅创建1个重复定时器,间隔可根据业务需求调整 self.batchTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(timerCalled) userInfo:nil repeats:YES]; } -(void)timerCalled{ if(stopBatch || self.iVal >= 10000) { [self.batchTimer invalidate]; self.batchTimer = nil; return; } // 单次执行10个步长,可根据需要调整 for (int i=0;i<10;i++) { self.iVal++; NSString *iString = [NSString stringWithFormat: @"%ld",self.iVal]; [textData setStringValue:iString]; } }
方案3:后台线程+主线程UI更新(性能最优)
仅需要将UI更新的代码包裹到主线程调度中,其余逻辑无需改动,即可充分利用多线程性能:
-(void)runBatchBackground{ stopBatch = false; dispatch_queue_t backgroundQueue = dispatch_queue_create("BatchQueue",nil); dispatch_async(backgroundQueue, ^(void){ for (NSInteger i=0;i<=10000 ;i++) { if(stopBatch) break; // 仅将UI更新操作抛到主线程执行 dispatch_async(dispatch_get_main_queue(), ^{ NSString *iString = [NSString stringWithFormat: @"%ld",i]; self.textData.stringValue = iString; }); // 循环执行过快时可加微小延时控制UI刷新频率,避免主线程负载过高 // usleep(1000); } }); }
内容的提问来源于stack exchange,提问作者SimonKravis
相关产品推荐
相关产品推荐

