1111#import < CoreFoundation/CoreFoundation.h>
1212#import " XLMJThread.h"
1313#import " LMJSettingCell.h"
14+
1415@interface LMJRunLoopViewController ()
1516/* * <#digest#> */
1617@property (nonatomic , strong ) XLMJThread *xlmjThread;
1718/* * <#digest#> */
18- @property (nonatomic , strong ) NSTimer *timer;
19+ @property (nonatomic , strong ) NSMutableArray <NSTimer *> *timers;
20+
21+ /* * <#digest#> */
22+ @property (nonatomic , strong ) NSMutableArray <NSThread *> *threads;
23+
1924@end
2025
2126@implementation LMJRunLoopViewController
2227
28+ static BOOL item01Operationed = NO ;
29+ static BOOL item02Operationed = NO ;
30+ static BOOL item1Operationed = NO ;
31+ static BOOL item3Operationed = NO ;
32+
2333- (void )viewDidLoad {
2434 [super viewDidLoad ];
2535 self.title = @" 看打印" ;
@@ -29,38 +39,59 @@ - (void)viewDidLoad {
2939 [weakself threadRunLoop ];
3040 };
3141
42+ LMJWordItem *item01 = [LMJWordItem itemWithTitle: @" 子线程定时器" subTitle: @" 思考定时器为什么不执行?" ];
43+ item01.itemOperation = ^(NSIndexPath *indexPath) {
44+ if (item01Operationed) {
45+ return ;
46+ }
47+ item01Operationed = YES ;
48+ [weakself timerOnChildThread ];
49+ };
50+
51+ LMJWordItem *item02 = [LMJWordItem itemWithTitle: @" 子线程定时器2" subTitle: @" 思考定时器为什么\" 执行\" ?" ];
52+ item02.itemOperation = ^(NSIndexPath *indexPath) {
53+ if (item02Operationed) {
54+ return ;
55+ }
56+ item02Operationed = YES ;
57+ [weakself timerOnChildThread2 ];
58+ };
3259
3360 LMJWordItem *item1 = [LMJWordItem itemWithTitle: @" 定时器和RunLoop" subTitle: nil ];
34- LMJWeakSelf (item1);
3561 item1.itemOperation = ^(NSIndexPath *indexPath) {
36- if (weakitem1. subTitle ) {
62+ if (item1Operationed ) {
3763 return ;
3864 }
39- weakitem1. subTitle = @" " ;
65+ item1Operationed = YES ;
4066 [weakself timerRunLoop ];
4167 };
4268
43- // LMJWordItem *item2 = [LMJWordItem itemWithTitle:@"RunLoop观察者" subTitle:@""];
44- // item2.itemOperation = ^(NSIndexPath *indexPath) {
45- // [weakself observerRunLoop];
46- // };
4769
4870 LMJWordItem *item3 = [LMJWordItem itemWithTitle: @" 1, 线程常驻:runLoop里边需要添加NSPort" subTitle: @" 2, 添加runloop观察者, 请点击多次看打印" ];
4971 item3.itemOperation = ^(NSIndexPath *indexPath) {
5072
51- static dispatch_once_t onceToken;
52- dispatch_once (&onceToken, ^{
53-
73+ if (!item3Operationed) {
5474 XLMJThread *thread = [[XLMJThread alloc ] initWithTarget: weakself selector: @selector (liveThread ) object: nil ];
5575 weakself.xlmjThread = thread;
5676 [thread start ];
57- });
77+ }
78+
79+ item3Operationed = YES ;
5880 // 在常驻线程执行
5981 [weakself performSelector: @selector (liveThreadRun ) onThread: weakself.xlmjThread withObject: nil waitUntilDone: NO ];
6082 };
6183
62- LMJItemSection *section0 = [LMJItemSection sectionWithItems: @[item0, item1, item3] andHeaderTitle: nil footerTitle: nil ];
84+ LMJItemSection *section0 = [LMJItemSection sectionWithItems: @[item0, item01, item02, item1, item3] andHeaderTitle: nil footerTitle: nil ];
6385 [self .sections addObject: section0];
86+
87+ UIButton *btn = [UIButton initWithFrame: CGRectMake (0 , 0 , 100 , 100 ) buttonTitle: @" 取消所有的定时器, 停止所有的线程, 恢复初始化" normalBGColor: [UIColor yellowColor ] selectBGColor: [UIColor whiteColor ] normalColor: [UIColor redColor ] selectColor: [UIColor greenColor ] buttonFont: [UIFont systemFontOfSize: 16 ] cornerRadius: 10 doneBlock: ^(UIButton *btn) {
88+
89+ [weakself cancelAndDissmissAll ];
90+ }];
91+
92+ btn.titleLabel .numberOfLines = 0 ;
93+
94+ self.tableView .tableFooterView = btn;
6495}
6596
6697- (void )liveThread
@@ -168,26 +199,40 @@ - (void)timerRunLoop
168199 NSLog (@" --runLoop--%p " , [NSRunLoop mainRunLoop ]);
169200
170201 // 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode
171- NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 2 target: self selector: @selector (run ) userInfo: nil repeats: YES ];
172- _timer = timer;
202+ NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector: @selector (run ) userInfo: nil repeats: YES ];
203+ [ self .timers addObject: timer] ;
173204 // 修改模式
174205 // 定时器会跑在标记为common modes的模式下
175206 // 标记为common modes的模式:UITrackingRunLoopMode和kCFRunLoopDefaultMode
176207 [[NSRunLoop currentRunLoop ] addTimer: timer forMode: NSRunLoopCommonModes ];
177208}
178209
179210- (void )dealloc {
180- [_timer invalidate ];
181- _timer = nil ;
211+ [self cancelAndDissmissAll ];
212+ }
213+
214+ - (void )cancelAndDissmissAll
215+ {
216+ [_timers makeObjectsPerformSelector: @selector (invalidate )];
217+ [_timers removeAllObjects ];
218+
219+ [_threads makeObjectsPerformSelector: @selector (cancel )];
220+ [_threads removeAllObjects ];
182221 [_xlmjThread cancel ];
183222 _xlmjThread = nil ;
223+
224+ item01Operationed = NO ;
225+ item02Operationed = NO ;
226+ item1Operationed = NO ;
227+ item3Operationed = NO ;
184228}
185229
186230- (void )threadRunLoop
187231{
188232 // 主运行循环
189233 NSLog (@" --runLoop--%p " , [NSRunLoop mainRunLoop ]);
190234 NSThread *thread = [[NSThread alloc ] initWithTarget: self selector: @selector (run ) object: nil ];
235+ [self .threads addObject: thread];
191236 [thread start ];
192237}
193238
@@ -198,6 +243,66 @@ - (void)run
198243 NSLog (@" --%@ ---" , [NSThread currentThread ]);
199244}
200245
246+ - (void )timerOnChildThread2
247+ {
248+ NSLog (@" -----runLoop--%p " , [NSRunLoop currentRunLoop ]);
249+ NSLog (@" --%@ ---" , [NSThread currentThread ]);
250+
251+ NSThread *thread = [[NSThread alloc ] initWithTarget: self selector: @selector (scheduledTimer2 ) object: nil ];
252+ [thread start ];
253+
254+ [self .threads addObject: thread];
255+ }
256+
257+ - (void )scheduledTimer2
258+ {
259+ NSLog (@" -----runLoop--%p " , [NSRunLoop currentRunLoop ]);
260+ NSLog (@" --%@ ---" , [NSThread currentThread ]);
261+
262+ NSLog (@" ----------run--- start -%@ " , [NSThread currentThread ]);
263+
264+ LMJWeakSelf (self);
265+ NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1 repeats: YES block: ^(NSTimer * _Nonnull timer) {
266+ [weakself run ];
267+ }];
268+ [self .timers addObject: timer];
269+ // 添加 port
270+ [[NSRunLoop currentRunLoop ] addPort: [NSPort port ] forMode: NSDefaultRunLoopMode ];
271+
272+ [[NSRunLoop currentRunLoop ] addTimer: timer forMode: NSRunLoopCommonModes ];
273+
274+ // 跑起来
275+ [[NSRunLoop currentRunLoop ] run ];
276+
277+ // 不会走的, 不会执行
278+ NSLog (@" ----------run-- end --%@ " , [NSThread currentThread ]);
279+ }
280+
281+ - (void )timerOnChildThread
282+ {
283+ NSLog (@" -----runLoop--%p " , [NSRunLoop currentRunLoop ]);
284+ NSLog (@" --%@ ---" , [NSThread currentThread ]);
285+
286+ NSThread *thread = [[NSThread alloc ] initWithTarget: self selector: @selector (scheduledTimer ) object: nil ];
287+ [thread start ];
288+
289+ [self .threads addObject: thread];
290+ }
291+
292+ - (void )scheduledTimer
293+ {
294+ NSLog (@" -----runLoop--%p " , [NSRunLoop currentRunLoop ]);
295+ NSLog (@" --%@ ---" , [NSThread currentThread ]);
296+ LMJWeakSelf (self);
297+ NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1 repeats: YES block: ^(NSTimer * _Nonnull timer) {
298+ [weakself run ];
299+ }];
300+ [self .timers addObject: timer];
301+ [[NSRunLoop currentRunLoop ] addTimer: timer forMode: NSRunLoopCommonModes ];
302+ }
303+
304+
305+ #pragma mark - no
201306- (UITableViewCell *)tableView : (UITableView *)tableView cellForRowAtIndexPath : (NSIndexPath *)indexPath
202307{
203308 [super tableView: tableView cellForRowAtIndexPath: indexPath];
@@ -243,4 +348,22 @@ - (void)rightButtonEvent:(UIButton *)sender navigationBar:(LMJNavigationBar *)na
243348
244349}
245350
351+ - (NSMutableArray <NSTimer *> *)timers
352+ {
353+ if (!_timers)
354+ {
355+ _timers = [NSMutableArray array ];
356+ }
357+ return _timers;
358+ }
359+
360+ - (NSMutableArray <NSThread *> *)threads
361+ {
362+ if (!_threads)
363+ {
364+ _threads = [NSMutableArray array ];
365+ }
366+ return _threads;
367+ }
368+
246369@end
0 commit comments