博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RunLoop
阅读量:7065 次
发布时间:2019-06-28

本文共 6440 字,大约阅读时间需要 21 分钟。

- (void)viewDidLoad {    [super viewDidLoad];        CFRunLoopRef ref = CFRunLoopGetMain();    CFArrayRef arr = CFRunLoopCopyAllModes(ref);    for (CFIndex i = 0; i < CFArrayGetCount(arr); i ++) {        NSString *str = (__bridge NSString *)CFArrayGetValueAtIndex(arr, i);        NSLog(@"AllMode:%@", str);    }        NSString *currentMode = (__bridge NSString *)CFRunLoopCopyCurrentMode(ref);    NSLog(@"currentMode:%@", currentMode);}复制代码

运行结果如下:

从运行结果来看,MainLoop所有模式有4种,但当前模式只有一种。

struct __CFRunLoop {    ... ...    pthread_t _pthread;    CFRunLoopModeRef _currentMode;    CFMutableSetRef _modes;    ... ...}复制代码

上面是__CFRunLoop的数据结构,可以看出_modes是Set类型,_currentMode只有一种。另外我们也可以看出__CFRunLoop是绑定了一个pthread_t的。

接下来我们来看一下__CFRunLoopMode。

struct __CFRunLoopMode {    ... ...    CFMutableSetRef     _sources0;    CFMutableSetRef     _sources1;    CFMutableArrayRef   _observers;    CFMutableArrayRef   _timers;    ... ...}复制代码

从_CFRunLoopMode的数据结构我们可以看出,mode包含三种类型的事件:source、observer、timer。

CFRunLoopTimer

接下来,我们来尝试实现一个timer。

- (void)viewDidLoad {    [super viewDidLoad];        CFRunLoopRef ref = CFRunLoopGetMain();        CFOptionFlags flag = kCFRunLoopBeforeTimers;    __block CFIndex i = 0;    CFRunLoopTimerRef timerRef = CFRunLoopTimerCreateWithHandler(CFAllocatorGetDefault(), CFAbsoluteTimeGetCurrent(), 0.1, flag, 0, ^(CFRunLoopTimerRef timer) {        i++;        NSLog(@"Test%ld: %f", i, CFRunLoopGetNextTimerFireDate(ref, kCFRunLoopDefaultMode));        if (i == 10) {            CFRunLoopTimerInvalidate(timer);            CFRunLoopRemoveTimer(ref, timer, kCFRunLoopDefaultMode);        }    });    CFRunLoopAddTimer(ref, timerRef, kCFRunLoopDefaultMode);}复制代码

运行结果如下:

CFRunLoopObserver

- (void)viewDidLoad {    [super viewDidLoad];        CFRunLoopRef ref = CFRunLoopGetMain();        CFRunLoopObserverRef observerRef = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {                if (activity == kCFRunLoopEntry) {            NSLog(@"Entry");        }                if (activity == kCFRunLoopBeforeTimers) {            NSLog(@"Timers");        }                if (activity == kCFRunLoopBeforeSources) {            NSLog(@"Source");        }                if (activity == kCFRunLoopBeforeWaiting) {            NSLog(@"BeforeWaiting");        }                if (activity == kCFRunLoopAfterWaiting) {            NSLog(@"AfterWaiting");        }                if (activity == kCFRunLoopRunStopped) {            NSLog(@"Stopped");        }    });    CFRunLoopAddObserver(ref, observerRef, kCFRunLoopDefaultMode);}复制代码

当应用处于等待时:

从运行结果上看,程序在停止等待后,会先创建timer,timer创建后发现无事可做,立刻被销毁,紧接着创建了source事件,然后开始等待接受事件。如此循环,而stopped却始终不会执行。如此便可保证程序一直在运行。

UITableView刷新优化

#import "ViewController.h"typedef void(^askMessageBlock)(void);typedef void(^reloadTableViewBlock)(void);@interface ViewController () 
@property (nonatomic, strong) UITableView *tableView;@property (nonatomic, copy) askMessageBlock askblock;@property (nonatomic, copy) reloadTableViewBlock reloadBlock;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; CFRunLoopRef ref = CFRunLoopGetMain(); _tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped]; _tableView.dataSource = self; _tableView.delegate = self; [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"TableCell"]; [self.view addSubview:_tableView]; CFRunLoopObserverRef observerRef = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { __block BOOL scrollEnd = YES; CFRunLoopPerformBlock(ref, UITrackingRunLoopMode, ^{ self.askblock = ^{ NSLog(@"Ask Message"); }; self.reloadBlock = ^{ NSLog(@"Reload TableView"); }; NSLog(@"TableView is Scrolling"); scrollEnd = NO; }); if (scrollEnd == YES) { if (activity == kCFRunLoopBeforeWaiting) { if (self.askblock) { self.askblock(); self.askblock = NULL; } } if (activity == kCFRunLoopAfterWaiting) { if (self.reloadBlock) { self.reloadBlock(); self.reloadBlock = NULL; } } } }); CFRunLoopAddObserver(ref, observerRef, kCFRunLoopDefaultMode);}#pragma mark - UITableViewDataSource- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 100;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TableCell"]; return cell;}#pragma mark - UITableViewDelegate- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end复制代码

提供一种思路,欢迎大神指导。

UITableView继承于UIScrollView,UIScrollView针对视图的滚动提供了相应的接口。

// 开始拖拽- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;// 已经开始滚动- (void)scrollViewDidScroll:(UIScrollView *)scrollView;// 开始减速- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;// 终止- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;复制代码

CFRunLoopSource

相较于timer和observer,source事件提供了两种sourceContext:CFRunloopSourceContext、CFRunLoopSourceContext1。下面我们来看一下两者的区别:

typedef struct {    ... ...        void (*schedule)(void *info, CFRunLoopRef rl, CFStringRef mode);    void (*cancel)(void *info, CFRunLoopRef rl, CFStringRef mode);    void (*perform)(void *info);} CFRunLoopSourceContext;typedef struct {    ... ...    void * (*getPort)(void *info);    void (*perform)(void *info);} CFRunLoopSourceContext1复制代码

这里省去了部分代码,主要看一下不同点。从两者的比较来看,CFRunLoopSourceContext1主要针对的是端口事件,CFRunLoopSourceContext针对触摸等事件。

CF_EXPORT CFRunLoopSourceRef CFRunLoopSourceCreate(CFAllocatorRef allocator, CFIndex order, CFRunLoopSourceContext *context);复制代码

CFRunLoop针对source事件只提供了一个构造方法。针对RunLoop的source事件,对应于手势事件、晃动事件、及远端事件。大家可以在上述事件的使用中去理解RunLoop的Source事件。

关于RunLoop就写到这里,以后有新的想法会及时补充与更正。

转载于:https://juejin.im/post/5adbdd16518825672b035049

你可能感兴趣的文章
在C#中调用API获取网络信息和流量
查看>>
Java集合遍历引发的"血案"
查看>>
Webpack入门教程六
查看>>
编译原理:正规式转变成DFA算法
查看>>
MongoDB数据库的MapReduce简单操作(转)
查看>>
cisco图标
查看>>
java获取类的信息
查看>>
Hibernate5-进阶添加工具类,对获取Session的方法封装
查看>>
通过内存映射文件来颠倒文本内容(暂没有处理Unicode和换行符)
查看>>
Debian软件包信息查询
查看>>
天猫物流提速背后:大数据加速颠覆传统零售业
查看>>
网页优化十大策略
查看>>
为每一个table单元格设置不同的背景颜色
查看>>
盘点智能硬件中那些脑洞大开的黑科技
查看>>
[HDFS Manual] CH4 HDFS High Availability Using the Quorum Journal Manager
查看>>
maven pom.xml详解
查看>>
活动目录数据库文件介绍
查看>>
Linux下配置tomcat+apr+native应对高并发
查看>>
html5播放mp4视频代码
查看>>
孟子>正文 活动目录(Active Directory)域故障解决实例(转载)
查看>>