Skip to content

Commit

Permalink
refactor: isInsecting to isIntersecting
Browse files Browse the repository at this point in the history
  • Loading branch information
zhoon committed May 18, 2022
1 parent 1be0419 commit c1205d0
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 41 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ IntersectionObserverContainerOptions *containerOptions = [IntersectionObserverCo
__strong __typeof(weakSelf)strongSelf = weakSelf;
for (NSInteger i = 0; i < entries.count; i++) {
IntersectionObserverEntry *entry = entries[i];
if (entry.isInsecting) {
if (entry.isIntersecting) {
// 进入可视区域
}
}
Expand Down
2 changes: 1 addition & 1 deletion ZHIntersectionObserver.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |spec|
#

spec.name = "ZHIntersectionObserver"
spec.version = "0.0.6-rc.4"
spec.version = "0.0.6"
spec.summary = "Intersection Observer for iOS."

# This description is used to generate tags and improve search results.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ - (void)initIntersectionObserver {
for (NSInteger i = 0; i < entries.count; i++) {
strongSelf.count++;
IntersectionObserverEntry *entry = entries[i];
entry.targetView.backgroundColor = entry.isInsecting ? [UIColor orangeColor] : [UIColor redColor];
NSLog(@"Example1: isInsecting = %@", @(entry.isInsecting));
entry.targetView.backgroundColor = entry.isIntersecting ? [UIColor orangeColor] : [UIColor redColor];
NSLog(@"Example1: isIntersecting = %@", @(entry.isIntersecting));
strongSelf.leftToplabel.text = strongSelf.rightToplabel.text = strongSelf.leftBottomlabel.text = strongSelf.rightBottomlabel.text = [NSString stringWithFormat:@"%@%@", @(ceil(entry.intersectionRatio * 100)), @"%"];
[strongSelf updateLabelText:[NSString stringWithFormat:@"可拖动 \n isInsecting = %@ \n changeCount = %@", @(entry.isInsecting), @(strongSelf.count)]];
[strongSelf updateLabelText:[NSString stringWithFormat:@"可拖动 \n isIntersecting = %@ \n changeCount = %@", @(entry.isIntersecting), @(strongSelf.count)]];
}
}];
self.containerView.intersectionObserverContainerOptions = containerOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ - (void)initIntersectionObserver {
for (NSInteger i = 0; i < entries.count; i++) {
IntersectionObserverEntry *entry = entries[i];
ZHExample2UITableViewCell *cell = (ZHExample2UITableViewCell *)entry.targetView;
NSLog(@"Example2 entry, isInsecting = %@ index = %@", @(entry.isInsecting), entry.data[@"row"]);
NSLog(@"Example2 entry, isIntersecting = %@ index = %@", @(entry.isIntersecting), entry.data[@"row"]);
if (cell) {
cell.backgroundColor = entry.isInsecting ? [[UIColor orangeColor] colorWithAlphaComponent:0.2] : [UIColor whiteColor];
cell.backgroundColor = entry.isIntersecting ? [[UIColor orangeColor] colorWithAlphaComponent:0.2] : [UIColor whiteColor];
}
}
}];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,16 @@ - (void)setupIntersectionObserver {

for (NSInteger i = 0; i < entries.count; i++) {
IntersectionObserverEntry *entry = entries[i];
if (entry.isInsecting) {
if (entry.isIntersecting) {
NSString *text = [NSString stringWithFormat:@"✅ 曝光:%@", [entry.data objectForKey:@"text"]];
NSString *newText = [NSString stringWithFormat:@"%@\n%@", text, strongSelf.logLabel.text ?: @""];
strongSelf.logLabel.text = [newText substringToIndex:MIN(180, newText.length)];
NSLog(@"Example3: dataKey = %@, isInsecting = %@", entry.dataKey, @(entry.isInsecting));
NSLog(@"Example3: dataKey = %@, isIntersecting = %@", entry.dataKey, @(entry.isIntersecting));
} else {
NSString *text = [NSString stringWithFormat:@"❌ 隐藏:%@", [entry.data objectForKey:@"text"]];
NSString *newText = [NSString stringWithFormat:@"%@\n%@", text, strongSelf.logLabel.text ?: @""];
strongSelf.logLabel.text = [newText substringToIndex:MIN(180, newText.length)];
NSLog(@"Example3: dataKey = %@, isInsecting = %@", entry.dataKey, @(entry.isInsecting));
NSLog(@"Example3: dataKey = %@, isIntersecting = %@", entry.dataKey, @(entry.isIntersecting));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ - (void)setupIntersectionObserver {

for (NSInteger i = 0; i < entries.count; i++) {
IntersectionObserverEntry *entry = entries[i];
if (entry.isInsecting) {
if (entry.isIntersecting) {
NSString *text = [NSString stringWithFormat:@"✅ 曝光:%@", [entry.data objectForKey:@"text"]];
NSString *newText = [NSString stringWithFormat:@"%@\n%@", text, strongSelf.logLabel.text ?: @""];
strongSelf.logLabel.text = newText;
Expand Down
4 changes: 2 additions & 2 deletions ZHIntersectionObserver/Source/IntersectionObserverEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ typedef void (^IntersectionObserverCallback)(NSString *scope, NSArray<Intersecti
@property(nonatomic, assign) CGFloat intersectionRatio;

/// 目标元素与容器相交,则返回 true。如果返回 true,则 IntersectionObserverEntry 描述了变换到交叉时的状态;如果返回 false,那么可以由此判断,变换是从交叉状态到非交叉状态
@property(nonatomic, assign) BOOL isInsecting;
@property(nonatomic, assign) BOOL isIntersecting;

/// 容器的 bounds
@property(nonatomic, assign) CGRect rootBounds;
Expand All @@ -53,7 +53,7 @@ typedef void (^IntersectionObserverCallback)(NSString *scope, NSArray<Intersecti
boundingClientRect:(CGRect)boundingClientRect
intersectionRatio:(CGFloat)intersectionRatio
intersectionRect:(CGRect)intersectionRect
isInsecting:(BOOL)isInsecting
isIntersecting:(BOOL)isIntersecting
rootBounds:(CGRect)rootBounds
time:(NSTimeInterval)time;

Expand Down
6 changes: 3 additions & 3 deletions ZHIntersectionObserver/Source/IntersectionObserverEntry.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ + (instancetype)initEntryWithTargetView:(UIView *)targetView
boundingClientRect:(CGRect)boundingClientRect
intersectionRatio:(CGFloat)intersectionRatio
intersectionRect:(CGRect)intersectionRect
isInsecting:(BOOL)isInsecting
isIntersecting:(BOOL)isIntersecting
rootBounds:(CGRect)rootBounds
time:(NSTimeInterval)time {
IntersectionObserverEntry *entry = [[IntersectionObserverEntry alloc] init];
entry.boundingClientRect = boundingClientRect;
entry.intersectionRatio = intersectionRatio;
entry.intersectionRect = intersectionRect;
entry.isInsecting = isInsecting;
entry.isIntersecting = isIntersecting;
entry.rootBounds = rootBounds;
entry.targetView = targetView;
entry.time = time;
Expand All @@ -32,7 +32,7 @@ + (instancetype)initEntryWithTargetView:(UIView *)targetView
}

- (NSString *)description {
return [NSString stringWithFormat:@"<%@, %p>: boundingClientRect = %@, intersectionRatio = %@, intersectionRect = %@, isInsecting = %@, rootBounds = %@, target = %@, time = %@, dataKey = %@ data = %@", self.class, self, @(_boundingClientRect), @(_intersectionRatio), @(_intersectionRect), @(_isInsecting), @(_rootBounds), _targetView, @(_time), _dataKey, _data];
return [NSString stringWithFormat:@"<%@, %p>: boundingClientRect = %@, intersectionRatio = %@, intersectionRect = %@, isIntersecting = %@, rootBounds = %@, target = %@, time = %@, dataKey = %@ data = %@", self.class, self, @(_boundingClientRect), @(_intersectionRatio), @(_intersectionRect), @(_isIntersecting), @(_rootBounds), _targetView, @(_time), _dataKey, _data];
}

@end
50 changes: 25 additions & 25 deletions ZHIntersectionObserver/Source/IntersectionObserverMeasure.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ + (void)measureWithObserver:(IntersectionObserver *)observer {

+ (void)measureWithObserver:(IntersectionObserver *)observer forTargetView:(UIView * __nullable)targetView {

// updateDataKey 调用后马上开始重新计算,但是这个时候如果是复用的 view 例如 cell,如果复用前和复用后位置不一样,那么在计算 isInsecting 的时候可能会错误。例如被复用的 view 在复用前是在屏幕外,那么复用的时候计算出来的 isInsecting 就是在屏幕外的,所以需要等待 view 重新布局之后再计算,通过 dispatch_async 使得计算再下个 runloop 再触发
// updateDataKey 调用后马上开始重新计算,但是这个时候如果是复用的 view 例如 cell,如果复用前和复用后位置不一样,那么在计算 isIntersecting 的时候可能会错误。例如被复用的 view 在复用前是在屏幕外,那么复用的时候计算出来的 isIntersecting 就是在屏幕外的,所以需要等待 view 重新布局之后再计算,通过 dispatch_async 使得计算再下个 runloop 再触发
dispatch_async(dispatch_get_main_queue(), ^{

IntersectionObserverContainerOptions *containerOptions = observer.containerOptions;
Expand Down Expand Up @@ -88,7 +88,7 @@ + (void)measureWithObserver:(IntersectionObserver *)observer forTargetView:(UIVi
CGRect intersectionRect = [[calcResult objectForKey:@"intersectionRect"] CGRectValue];

BOOL isReused = NO;
BOOL isInsecting = [self isInsectingWithRatio:ratio containerOptions:containerOptions targetOptions:options];
BOOL isIntersecting = [self isIntersectingWithRatio:ratio containerOptions:containerOptions targetOptions:options];

void (^delayRemoveReuseDataKey)(void) = ^void() {
NSString *dataKey = options.dataKey;
Expand All @@ -110,7 +110,7 @@ + (void)measureWithObserver:(IntersectionObserver *)observer forTargetView:(UIVi
boundingClientRect:targetViewportRect
intersectionRatio:ratio
intersectionRect:intersectionRect
isInsecting:NO
isIntersecting:NO
rootBounds:containerView.bounds
time:floor([NSDate date].timeIntervalSince1970 * 1000)];
// 把被复用的 dataKey 添加到一个复用池中
Expand All @@ -120,8 +120,8 @@ + (void)measureWithObserver:(IntersectionObserver *)observer forTargetView:(UIVi
}
// 不能放到上面 if 里面,否则当可视的 dataKey1 复用了不可视的 dataKey3,可视的 dataKey1 不会走 remove,
// 从而导致这个可视的 dataKey1 被可视的 dataKey2 复用之后加入复用池后没有被移除,所以会收到多余的 hide 事件通知
if (isInsecting) {
// 被复用并且 isInsecting = YES 需要延迟移除,避免收到 hide 事件通知
if (isIntersecting) {
// 被复用并且 isIntersecting = YES 需要延迟移除,避免收到 hide 事件通知
isReused = YES;
delayRemoveReuseDataKey();
}
Expand All @@ -141,10 +141,10 @@ + (void)measureWithObserver:(IntersectionObserver *)observer forTargetView:(UIVi
boundingClientRect:targetViewportRect
intersectionRatio:ratio
intersectionRect:intersectionRect
isInsecting:isInsecting
isIntersecting:isIntersecting
rootBounds:containerView.bounds
time:floor([NSDate date].timeIntervalSince1970 * 1000)];
if (isInsecting) {
if (isIntersecting) {
// NSLog(@"showEntry %@", options.dataKey);
[entries addObject:entry];
} else {
Expand Down Expand Up @@ -255,9 +255,9 @@ + (void)delayMeasureWithObserver:(IntersectionObserver *)observer
CGRect targetViewportRect = [[calcResult objectForKey:@"targetViewportRect"] CGRectValue];
CGRect intersectionRect = [[calcResult objectForKey:@"intersectionRect"] CGRectValue];

BOOL isInsecting = [self isInsectingWithRatio:ratio containerOptions:containerOptions targetOptions:options];
BOOL isIntersecting = [self isIntersectingWithRatio:ratio containerOptions:containerOptions targetOptions:options];
BOOL isDataKeyVisible = [[IntersectionObserverReuseManager shareInstance] isDataKeyVisible:oldEntry.dataKey inScope:scope];
BOOL canReport = [oldEntry.dataKey isEqualToString:options.dataKey] && isInsecting == oldEntry.isInsecting && !isDataKeyVisible;
BOOL canReport = [oldEntry.dataKey isEqualToString:options.dataKey] && isIntersecting == oldEntry.isIntersecting && !isDataKeyVisible;

// 不需要更新 ratio,都是 delay 前就更新了
options.preDataKey = options.dataKey;
Expand All @@ -271,7 +271,7 @@ + (void)delayMeasureWithObserver:(IntersectionObserver *)observer
boundingClientRect:targetViewportRect
intersectionRatio:ratio
intersectionRect:intersectionRect
isInsecting:isInsecting
isIntersecting:isIntersecting
rootBounds:containerView.bounds
time:floor([NSDate date].timeIntervalSince1970 * 1000)];
[filterEntries addObject:entry];
Expand Down Expand Up @@ -352,24 +352,24 @@ + (BOOL)canReportWithRatio:(CGFloat)ratio
targetOptions:(IntersectionObserverTargetOptions *)targetOptions {

CGFloat preRatio = [[IntersectionObserverReuseManager shareInstance] ratioForDataKey:targetOptions.dataKey inScope:containerOptions.scope];
BOOL isInsecting = [self isInsectingWithRatio:ratio containerOptions:containerOptions targetOptions:targetOptions];
BOOL isIntersecting = [self isIntersectingWithRatio:ratio containerOptions:containerOptions targetOptions:targetOptions];
BOOL isDataKeyVisible = targetOptions.dataKey ? [[IntersectionObserverReuseManager shareInstance] isDataKeyVisible:targetOptions.dataKey inScope:containerOptions.scope] : NO;

// 生命周期发生变化
if (containerOptions.measureWhenAppStateChanged && NotEmptyString(targetOptions.dataKey)) {
UIApplicationState prevApplicationState = [IntersectionObserverManager shareInstance].previousApplicationState;
if (prevApplicationState != UIApplicationStateActive &&
UIApplication.sharedApplication.applicationState == UIApplicationStateActive) {
// 重新计算,只要是 isInsecting 即可发送事件。如果没有设置 dataKey,回到前台会多发送一次曝光事件,所以屏蔽一下。
// 重新计算,只要是 isIntersecting 即可发送事件。如果没有设置 dataKey,回到前台会多发送一次曝光事件,所以屏蔽一下。
if (targetOptions.dataKey) {
return isInsecting;
return isIntersecting;
}
return NO;
}
if (prevApplicationState != UIApplicationStateBackground &&
UIApplication.sharedApplication.applicationState == UIApplicationStateBackground) {
// 直接返回 YES 会导致那些那些一开始没曝光的 item 会发送多 isInsecting = NO 的通知
// 如果改为 isInsecting != preInsecting 会导致 cell 不复用的情况切换前后台无法触发事件,所以需要通过 updateOptionsPreProperties:fromOldOptions 同步一下 options,但是还是会存在之前非曝光过的被复用到曝光的时候,isInsecting != preInsecting 为 NO(isInsecting 必定为 NO,没曝光的 item 的 preInsecting 也是 NO),导致当前没有发送 isInsecting = NO 事件,所以最后改成 isDataKeyVisible,但是要求设置 dataKey 才能生效。
// 直接返回 YES 会导致那些那些一开始没曝光的 item 会发送多 isIntersecting = NO 的通知
// 如果改为 isIntersecting != preInsecting 会导致 cell 不复用的情况切换前后台无法触发事件,所以需要通过 updateOptionsPreProperties:fromOldOptions 同步一下 options,但是还是会存在之前非曝光过的被复用到曝光的时候,isIntersecting != preInsecting 为 NO(isIntersecting 必定为 NO,没曝光的 item 的 preInsecting 也是 NO),导致当前没有发送 isIntersecting = NO 事件,所以最后改成 isDataKeyVisible,但是要求设置 dataKey 才能生效。
return [[IntersectionObserverReuseManager shareInstance] isDataKeyVisible:targetOptions.dataKey inScope:containerOptions.scope];
}
}
Expand All @@ -379,26 +379,26 @@ + (BOOL)canReportWithRatio:(CGFloat)ratio
BOOL targetViewVisible = [self isTargetViewVisible:targetOptions.targetView inContainerView:containerOptions.containerView];
BOOL containerViewVisible = [self isContainerViewVisible:containerOptions.containerView];
if (targetViewVisible != targetOptions.preVisible || containerViewVisible != containerOptions.preVisible) {
return isInsecting ? !isDataKeyVisible : isDataKeyVisible;
return isIntersecting ? !isDataKeyVisible : isDataKeyVisible;
}
}

// 数据发生变化(或者复用)
if (NotEmptyString(targetOptions.dataKey) && NotEmptyString(targetOptions.preDataKey) && ![targetOptions.dataKey isEqualToString:targetOptions.preDataKey]) {
// NSLog(@"数据变化 dataChange %@ %@ %@", targetOptions.dataKey, @(isInsecting), @(isDataKeyVisible));
return isInsecting ? !isDataKeyVisible : isDataKeyVisible;
// NSLog(@"数据变化 dataChange %@ %@ %@", targetOptions.dataKey, @(isIntersecting), @(isDataKeyVisible));
return isIntersecting ? !isDataKeyVisible : isDataKeyVisible;
}

// 前后 ratio 变化
BOOL preInsecting = [self isInsectingWithRatio:preRatio containerOptions:containerOptions targetOptions:targetOptions];
if (isInsecting != preInsecting) {
BOOL preInsecting = [self isIntersectingWithRatio:preRatio containerOptions:containerOptions targetOptions:targetOptions];
if (isIntersecting != preInsecting) {
// NSLog(@"前后 ratio 变化 %@ %@ %@ %@", targetOptions.dataKey, @(ratio), @(preRatio), @(isDataKeyVisible));
return isInsecting ? !isDataKeyVisible : isDataKeyVisible;
return isIntersecting ? !isDataKeyVisible : isDataKeyVisible;
}

// 是否达到某个 ratio
BOOL reachRatio = [self lastMatchThreshold:containerOptions.thresholds ratio:ratio] != [self lastMatchThreshold:containerOptions.thresholds ratio:preRatio];
// NSLog(@"达到 reachRatio %@ %@ %@ %@ %@", targetOptions.dataKey, @(ratio), @(preRatio), @(isInsecting), @(reachRatio));
// NSLog(@"达到 reachRatio %@ %@ %@ %@ %@", targetOptions.dataKey, @(ratio), @(preRatio), @(isIntersecting), @(reachRatio));
return reachRatio;
}

Expand Down Expand Up @@ -426,9 +426,9 @@ + (BOOL)isTargetViewVisible:(UIView *)targetView inContainerView:(UIView *)conta
return visible;
}

+ (BOOL)isInsectingWithRatio:(CGFloat)ratio
containerOptions:(IntersectionObserverContainerOptions *)containerOptions
targetOptions:(IntersectionObserverTargetOptions *)targetOptions {
+ (BOOL)isIntersectingWithRatio:(CGFloat)ratio
containerOptions:(IntersectionObserverContainerOptions *)containerOptions
targetOptions:(IntersectionObserverTargetOptions *)targetOptions {
if (containerOptions.measureWhenAppStateChanged &&
UIApplication.sharedApplication.applicationState == UIApplicationStateBackground) {
return NO;
Expand Down

0 comments on commit c1205d0

Please sign in to comment.