blob: 7e8fa98f8d18380de256703564a656d6b0a3a907 [file] [log] [blame]
/**
* Copyright 2018 Alibaba Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "EBExpressionTiming.h"
#import <UIKit/UIKit.h>
@interface EBExpressionTiming ()
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic, assign) CFTimeInterval duration;
@end
@implementation EBExpressionTiming
- (instancetype)init {
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
+ (BOOL)requireSource {
return NO;
}
- (void)updateTargetExpression:(NSMapTable<id,NSDictionary *> *)targetExpression
options:(NSDictionary *)options
exitExpression:(NSDictionary *)exitExpression
callback:(EBKeepAliveCallback)callback {
[super updateTargetExpression:targetExpression
options:options
exitExpression:exitExpression
callback:callback];
[self initDisplayLink];
}
- (void)applicationWillResignActive:(NSNotification *)notification
{
[self.displayLink setPaused:YES];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
[self.displayLink setPaused:NO];
}
- (void)removeExpressionBinding {
[super removeExpressionBinding];
if (self.displayLink) {
[self.displayLink invalidate];
self.displayLink = nil;
}
}
#pragma mark - Private methods
- (void)initDisplayLink {
self.duration = 0;
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplay)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[self.displayLink setPaused:NO];
[self fireStateChangedEvent:@"start"];
}
- (void)handleDisplay {
@try {
NSDictionary *scope = [self setUpScope];
BOOL exit = ![self executeExpression:scope];
if (exit) {
[self.displayLink invalidate];
self.displayLink = nil;
[self fireStateChangedEvent:@"exit"];
}
} @catch (NSException *exception) {
NSLog(@"%@",exception);
}
}
- (NSDictionary *)setUpScope {
NSMutableDictionary *scope = [self generalScope];
self.duration += (self.displayLink.duration * 1000);
[scope setValue:@(self.duration) forKey:@"t"];
return [scope copy];
}
- (void)fireStateChangedEvent:(NSString *)state {
NSDictionary *result = @{@"t": @(_duration),
@"state": state};
if (self.callback) {
self.callback(self.source, result, YES);
}
}
@end