1
This commit is contained in:
41
Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.h
generated
Normal file
41
Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.h
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIView+LookinMobile.h
|
||||
// WeRead
|
||||
//
|
||||
// Created by Li Kai on 2018/11/30.
|
||||
// Copyright © 2018 tencent. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LookinDefines.h"
|
||||
#import "TargetConditionals.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CALayer (LookinServer)
|
||||
|
||||
/// 如果 myView.layer == myLayer,则 myLayer.lks_hostView 会返回 myView
|
||||
@property(nonatomic, readonly, weak) UIView *lks_hostView;
|
||||
|
||||
- (UIWindow *)lks_window;
|
||||
|
||||
- (CGRect)lks_frameInWindow:(UIWindow *)window;
|
||||
|
||||
- (UIImage *)lks_groupScreenshotWithLowQuality:(BOOL)lowQuality;
|
||||
/// 当没有 sublayers 时,该方法返回 nil
|
||||
- (UIImage *)lks_soloScreenshotWithLowQuality:(BOOL)lowQuality;
|
||||
|
||||
/// 获取和该对象有关的对象的 Class 层级树
|
||||
- (NSArray<NSArray<NSString *> *> *)lks_relatedClassChainList;
|
||||
|
||||
- (NSArray<NSString *> *)lks_selfRelation;
|
||||
|
||||
@property(nonatomic, strong) UIColor *lks_backgroundColor;
|
||||
@property(nonatomic, strong) UIColor *lks_borderColor;
|
||||
@property(nonatomic, strong) UIColor *lks_shadowColor;
|
||||
@property(nonatomic, assign) CGFloat lks_shadowOffsetWidth;
|
||||
@property(nonatomic, assign) CGFloat lks_shadowOffsetHeight;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
233
Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.m
generated
Normal file
233
Pods/LookinServer/Src/Main/Server/Category/CALayer+LookinServer.m
generated
Normal file
@@ -0,0 +1,233 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIView+LookinMobile.m
|
||||
// WeRead
|
||||
//
|
||||
// Created by Li Kai on 2018/11/30.
|
||||
// Copyright © 2018 tencent. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CALayer+LookinServer.h"
|
||||
#import "LKS_HierarchyDisplayItemsMaker.h"
|
||||
#import "LookinDisplayItem.h"
|
||||
#import <objc/runtime.h>
|
||||
#import "LKS_ConnectionManager.h"
|
||||
#import "LookinIvarTrace.h"
|
||||
#import "LookinServerDefines.h"
|
||||
#import "UIColor+LookinServer.h"
|
||||
#import "LKS_MultiplatformAdapter.h"
|
||||
|
||||
@implementation CALayer (LookinServer)
|
||||
|
||||
- (UIWindow *)lks_window {
|
||||
CALayer *layer = self;
|
||||
while (layer) {
|
||||
UIView *hostView = layer.lks_hostView;
|
||||
if (hostView.window) {
|
||||
return hostView.window;
|
||||
} else if ([hostView isKindOfClass:[UIWindow class]]) {
|
||||
return (UIWindow *)hostView;
|
||||
}
|
||||
layer = layer.superlayer;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CGRect)lks_frameInWindow:(UIWindow *)window {
|
||||
UIWindow *selfWindow = [self lks_window];
|
||||
if (!selfWindow) {
|
||||
return CGRectZero;
|
||||
}
|
||||
|
||||
CGRect rectInSelfWindow = [selfWindow.layer convertRect:self.frame fromLayer:self.superlayer];
|
||||
CGRect rectInWindow = [window convertRect:rectInSelfWindow fromWindow:selfWindow];
|
||||
return rectInWindow;
|
||||
}
|
||||
|
||||
#pragma mark - Host View
|
||||
|
||||
- (UIView *)lks_hostView {
|
||||
if (self.delegate && [self.delegate isKindOfClass:UIView.class]) {
|
||||
UIView *view = (UIView *)self.delegate;
|
||||
if (view.layer == self) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - Screenshot
|
||||
|
||||
- (UIImage *)lks_groupScreenshotWithLowQuality:(BOOL)lowQuality {
|
||||
|
||||
CGFloat screenScale = [LKS_MultiplatformAdapter mainScreenScale];
|
||||
CGFloat pixelWidth = self.frame.size.width * screenScale;
|
||||
CGFloat pixelHeight = self.frame.size.height * screenScale;
|
||||
if (pixelWidth <= 0 || pixelHeight <= 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGFloat renderScale = lowQuality ? 1 : 0;
|
||||
CGFloat maxLength = MAX(pixelWidth, pixelHeight);
|
||||
if (maxLength > LookinNodeImageMaxLengthInPx) {
|
||||
// 确保最终绘制出的图片长和宽都不能超过 LookinNodeImageMaxLengthInPx
|
||||
// 如果算出的 renderScale 大于 1 则取 1,因为似乎用 1 渲染的速度要比一个别的奇怪的带小数点的数字要更快
|
||||
renderScale = MIN(screenScale * LookinNodeImageMaxLengthInPx / maxLength, 1);
|
||||
}
|
||||
|
||||
CGSize contextSize = self.frame.size;
|
||||
if (contextSize.width <= 0 || contextSize.height <= 0 || contextSize.width > 20000 || contextSize.height > 20000) {
|
||||
NSLog(@"LookinServer - Failed to capture screenshot. Invalid context size: %@ x %@", @(contextSize.width), @(contextSize.height));
|
||||
return nil;
|
||||
}
|
||||
UIGraphicsBeginImageContextWithOptions(contextSize, NO, renderScale);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
if (self.lks_hostView && !self.lks_hostView.lks_isChildrenViewOfTabBar) {
|
||||
[self.lks_hostView drawViewHierarchyInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) afterScreenUpdates:YES];
|
||||
} else {
|
||||
[self renderInContext:context];
|
||||
}
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
- (UIImage *)lks_soloScreenshotWithLowQuality:(BOOL)lowQuality {
|
||||
if (!self.sublayers.count) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGFloat screenScale = [LKS_MultiplatformAdapter mainScreenScale];
|
||||
CGFloat pixelWidth = self.frame.size.width * screenScale;
|
||||
CGFloat pixelHeight = self.frame.size.height * screenScale;
|
||||
if (pixelWidth <= 0 || pixelHeight <= 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGFloat renderScale = lowQuality ? 1 : 0;
|
||||
CGFloat maxLength = MAX(pixelWidth, pixelHeight);
|
||||
if (maxLength > LookinNodeImageMaxLengthInPx) {
|
||||
// 确保最终绘制出的图片长和宽都不能超过 LookinNodeImageMaxLengthInPx
|
||||
// 如果算出的 renderScale 大于 1 则取 1,因为似乎用 1 渲染的速度要比一个别的奇怪的带小数点的数字要更快
|
||||
renderScale = MIN(screenScale * LookinNodeImageMaxLengthInPx / maxLength, 1);
|
||||
}
|
||||
|
||||
if (self.sublayers.count) {
|
||||
NSArray<CALayer *> *sublayers = [self.sublayers copy];
|
||||
NSMutableArray<CALayer *> *visibleSublayers = [NSMutableArray arrayWithCapacity:sublayers.count];
|
||||
[sublayers enumerateObjectsUsingBlock:^(__kindof CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (!sublayer.hidden) {
|
||||
sublayer.hidden = YES;
|
||||
[visibleSublayers addObject:sublayer];
|
||||
}
|
||||
}];
|
||||
|
||||
CGSize contextSize = self.frame.size;
|
||||
if (contextSize.width <= 0 || contextSize.height <= 0 || contextSize.width > 20000 || contextSize.height > 20000) {
|
||||
NSLog(@"LookinServer - Failed to capture screenshot. Invalid context size: %@ x %@", @(contextSize.width), @(contextSize.height));
|
||||
return nil;
|
||||
}
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(contextSize, NO, renderScale);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
if (self.lks_hostView && !self.lks_hostView.lks_isChildrenViewOfTabBar) {
|
||||
[self.lks_hostView drawViewHierarchyInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) afterScreenUpdates:YES];
|
||||
} else {
|
||||
[self renderInContext:context];
|
||||
}
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
[visibleSublayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull sublayer, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
sublayer.hidden = NO;
|
||||
}];
|
||||
|
||||
return image;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray<NSArray<NSString *> *> *)lks_relatedClassChainList {
|
||||
NSMutableArray *array = [NSMutableArray arrayWithCapacity:2];
|
||||
if (self.lks_hostView) {
|
||||
[array addObject:[CALayer lks_getClassListOfObject:self.lks_hostView endingClass:@"UIView"]];
|
||||
UIViewController* vc = [self.lks_hostView lks_findHostViewController];
|
||||
if (vc) {
|
||||
[array addObject:[CALayer lks_getClassListOfObject:vc endingClass:@"UIViewController"]];
|
||||
}
|
||||
} else {
|
||||
[array addObject:[CALayer lks_getClassListOfObject:self endingClass:@"CALayer"]];
|
||||
}
|
||||
return array.copy;
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> *)lks_getClassListOfObject:(id)object endingClass:(NSString *)endingClass {
|
||||
NSArray<NSString *> *completedList = [object lks_classChainList];
|
||||
NSUInteger endingIdx = [completedList indexOfObject:endingClass];
|
||||
if (endingIdx != NSNotFound) {
|
||||
completedList = [completedList subarrayWithRange:NSMakeRange(0, endingIdx + 1)];
|
||||
}
|
||||
return completedList;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)lks_selfRelation {
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
NSMutableArray<LookinIvarTrace *> *ivarTraces = [NSMutableArray array];
|
||||
if (self.lks_hostView) {
|
||||
UIViewController* vc = [self.lks_hostView lks_findHostViewController];
|
||||
if (vc) {
|
||||
[array addObject:[NSString stringWithFormat:@"(%@ *).view", NSStringFromClass(vc.class)]];
|
||||
|
||||
[ivarTraces addObjectsFromArray:vc.lks_ivarTraces];
|
||||
}
|
||||
[ivarTraces addObjectsFromArray:self.lks_hostView.lks_ivarTraces];
|
||||
} else {
|
||||
[ivarTraces addObjectsFromArray:self.lks_ivarTraces];
|
||||
}
|
||||
if (ivarTraces.count) {
|
||||
[array addObjectsFromArray:[ivarTraces lookin_map:^id(NSUInteger idx, LookinIvarTrace *value) {
|
||||
return [NSString stringWithFormat:@"(%@ *) -> %@", value.hostClassName, value.ivarName];
|
||||
}]];
|
||||
}
|
||||
return array.count ? array.copy : nil;
|
||||
}
|
||||
|
||||
- (UIColor *)lks_backgroundColor {
|
||||
return [UIColor lks_colorWithCGColor:self.backgroundColor];
|
||||
}
|
||||
- (void)setLks_backgroundColor:(UIColor *)lks_backgroundColor {
|
||||
self.backgroundColor = lks_backgroundColor.CGColor;
|
||||
}
|
||||
|
||||
- (UIColor *)lks_borderColor {
|
||||
return [UIColor lks_colorWithCGColor:self.borderColor];
|
||||
}
|
||||
- (void)setLks_borderColor:(UIColor *)lks_borderColor {
|
||||
self.borderColor = lks_borderColor.CGColor;
|
||||
}
|
||||
|
||||
- (UIColor *)lks_shadowColor {
|
||||
return [UIColor lks_colorWithCGColor:self.shadowColor];
|
||||
}
|
||||
- (void)setLks_shadowColor:(UIColor *)lks_shadowColor {
|
||||
self.shadowColor = lks_shadowColor.CGColor;
|
||||
}
|
||||
|
||||
- (CGFloat)lks_shadowOffsetWidth {
|
||||
return self.shadowOffset.width;
|
||||
}
|
||||
- (void)setLks_shadowOffsetWidth:(CGFloat)lks_shadowOffsetWidth {
|
||||
self.shadowOffset = CGSizeMake(lks_shadowOffsetWidth, self.shadowOffset.height);
|
||||
}
|
||||
|
||||
- (CGFloat)lks_shadowOffsetHeight {
|
||||
return self.shadowOffset.height;
|
||||
}
|
||||
- (void)setLks_shadowOffsetHeight:(CGFloat)lks_shadowOffsetHeight {
|
||||
self.shadowOffset = CGSizeMake(self.shadowOffset.width, lks_shadowOffsetHeight);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
41
Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.h
generated
Normal file
41
Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.h
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// NSObject+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/4/21.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "LookinDefines.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class LookinIvarTrace;
|
||||
|
||||
@interface NSObject (LookinServer)
|
||||
|
||||
#pragma mark - oid
|
||||
|
||||
/// 如果 oid 不存在则会创建新的 oid
|
||||
- (unsigned long)lks_registerOid;
|
||||
|
||||
/// 0 表示不存在
|
||||
@property(nonatomic, assign) unsigned long lks_oid;
|
||||
|
||||
+ (NSObject *)lks_objectWithOid:(unsigned long)oid;
|
||||
|
||||
#pragma mark - trace
|
||||
|
||||
@property(nonatomic, copy) NSString *lks_specialTrace;
|
||||
|
||||
+ (void)lks_clearAllObjectsTraces;
|
||||
|
||||
/**
|
||||
获取当前对象的 Class 层级树,如 @[@"UIView", @"UIResponder", @"NSObject"]。未 demangle,有 Swift Module Name
|
||||
*/
|
||||
- (NSArray<NSString *> *)lks_classChainList;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
99
Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.m
generated
Normal file
99
Pods/LookinServer/Src/Main/Server/Category/NSObject+LookinServer.m
generated
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// NSObject+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/4/21.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "NSObject+Lookin.h"
|
||||
#import "NSObject+LookinServer.h"
|
||||
#import "LookinServerDefines.h"
|
||||
#import "LKS_ObjectRegistry.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@implementation NSObject (LookinServer)
|
||||
|
||||
#pragma mark - oid
|
||||
|
||||
- (unsigned long)lks_registerOid {
|
||||
if (!self.lks_oid) {
|
||||
unsigned long oid = [[LKS_ObjectRegistry sharedInstance] addObject:self];
|
||||
self.lks_oid = oid;
|
||||
}
|
||||
return self.lks_oid;
|
||||
}
|
||||
|
||||
- (void)setLks_oid:(unsigned long)lks_oid {
|
||||
[self lookin_bindObject:@(lks_oid) forKey:@"lks_oid"];
|
||||
}
|
||||
|
||||
- (unsigned long)lks_oid {
|
||||
NSNumber *number = [self lookin_getBindObjectForKey:@"lks_oid"];
|
||||
return [number unsignedLongValue];
|
||||
}
|
||||
|
||||
+ (NSObject *)lks_objectWithOid:(unsigned long)oid {
|
||||
return [[LKS_ObjectRegistry sharedInstance] objectWithOid:oid];
|
||||
}
|
||||
|
||||
#pragma mark - trace
|
||||
|
||||
- (void)setLks_ivarTraces:(NSArray<LookinIvarTrace *> *)lks_ivarTraces {
|
||||
[self lookin_bindObject:lks_ivarTraces.copy forKey:@"lks_ivarTraces"];
|
||||
|
||||
if (lks_ivarTraces) {
|
||||
[[NSObject lks_allObjectsWithTraces] addPointer:(void *)self];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray<LookinIvarTrace *> *)lks_ivarTraces {
|
||||
return [self lookin_getBindObjectForKey:@"lks_ivarTraces"];
|
||||
}
|
||||
|
||||
- (void)setLks_specialTrace:(NSString *)lks_specialTrace {
|
||||
[self lookin_bindObject:lks_specialTrace forKey:@"lks_specialTrace"];
|
||||
if (lks_specialTrace) {
|
||||
[[NSObject lks_allObjectsWithTraces] addPointer:(void *)self];
|
||||
}
|
||||
}
|
||||
- (NSString *)lks_specialTrace {
|
||||
return [self lookin_getBindObjectForKey:@"lks_specialTrace"];
|
||||
}
|
||||
|
||||
+ (void)lks_clearAllObjectsTraces {
|
||||
[[[NSObject lks_allObjectsWithTraces] allObjects] enumerateObjectsUsingBlock:^(NSObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
obj.lks_ivarTraces = nil;
|
||||
obj.lks_specialTrace = nil;
|
||||
}];
|
||||
[NSObject lks_allObjectsWithTraces].count = 0;
|
||||
}
|
||||
|
||||
+ (NSPointerArray *)lks_allObjectsWithTraces {
|
||||
static dispatch_once_t onceToken;
|
||||
static NSPointerArray *lks_allObjectsWithTraces = nil;
|
||||
dispatch_once(&onceToken,^{
|
||||
lks_allObjectsWithTraces = [NSPointerArray weakObjectsPointerArray];
|
||||
});
|
||||
return lks_allObjectsWithTraces;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)lks_classChainList {
|
||||
NSMutableArray<NSString *> *classChainList = [NSMutableArray array];
|
||||
Class currentClass = self.class;
|
||||
|
||||
while (currentClass) {
|
||||
NSString *currentClassName = NSStringFromClass(currentClass);
|
||||
if (currentClassName) {
|
||||
[classChainList addObject:currentClassName];
|
||||
}
|
||||
currentClass = [currentClass superclass];
|
||||
}
|
||||
return classChainList.copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
21
Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.h
generated
Normal file
21
Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIBlurEffect+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/10/8.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIBlurEffect (LookinServer)
|
||||
|
||||
/// 该 number 包装的对象是 UIBlurEffectStyle,之所以用 NSNumber 是因为想把 0 和 nil 区分开,毕竟这里是在 hook 系统,稳一点好。
|
||||
/// 该方法的实现需要 Hook,因此若定义了 LOOKIN_SERVER_DISABLE_HOOK 宏,则属性会返回 nil
|
||||
@property(nonatomic, strong) NSNumber *lks_effectStyleNumber;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
57
Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.m
generated
Normal file
57
Pods/LookinServer/Src/Main/Server/Category/UIBlurEffect+LookinServer.m
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIBlurEffect+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/10/8.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UIBlurEffect+LookinServer.h"
|
||||
#import "NSObject+Lookin.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@implementation UIBlurEffect (LookinServer)
|
||||
|
||||
#ifdef LOOKIN_SERVER_DISABLE_HOOK
|
||||
|
||||
- (void)setLks_effectStyleNumber:(NSNumber *)lks_effectStyleNumber {
|
||||
}
|
||||
|
||||
- (NSNumber *)lks_effectStyleNumber {
|
||||
return nil;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
+ (void)load {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
Method oriMethod = class_getClassMethod([self class], @selector(effectWithStyle:));
|
||||
Method newMethod = class_getClassMethod([self class], @selector(lks_effectWithStyle:));
|
||||
method_exchangeImplementations(oriMethod, newMethod);
|
||||
});
|
||||
}
|
||||
|
||||
+ (UIBlurEffect *)lks_effectWithStyle:(UIBlurEffectStyle)style {
|
||||
id effect = [self lks_effectWithStyle:style];
|
||||
if ([effect respondsToSelector:@selector(setLks_effectStyleNumber:)]) {
|
||||
[effect setLks_effectStyleNumber:@(style)];
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
||||
- (void)setLks_effectStyleNumber:(NSNumber *)lks_effectStyleNumber {
|
||||
[self lookin_bindObject:lks_effectStyleNumber forKey:@"lks_effectStyleNumber"];
|
||||
}
|
||||
|
||||
- (NSNumber *)lks_effectStyleNumber {
|
||||
return [self lookin_getBindObjectForKey:@"lks_effectStyleNumber"];
|
||||
}
|
||||
|
||||
#endif /* LOOKIN_SERVER_DISABLE_HOOK */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
26
Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.h
generated
Normal file
26
Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.h
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIColor+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/6/5.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIColor (LookinServer)
|
||||
|
||||
- (NSArray<NSNumber *> *)lks_rgbaComponents;
|
||||
+ (instancetype)lks_colorFromRGBAComponents:(NSArray<NSNumber *> *)components;
|
||||
|
||||
- (NSString *)lks_rgbaString;
|
||||
- (NSString *)lks_hexString;
|
||||
|
||||
/// will check if the argument is a real CGColor
|
||||
+ (UIColor *)lks_colorWithCGColor:(CGColorRef)cgColor;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
183
Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.m
generated
Normal file
183
Pods/LookinServer/Src/Main/Server/Category/UIColor+LookinServer.m
generated
Normal file
@@ -0,0 +1,183 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIColor+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/6/5.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UIColor+LookinServer.h"
|
||||
|
||||
@implementation UIColor (LookinServer)
|
||||
|
||||
- (NSArray<NSNumber *> *)lks_rgbaComponents {
|
||||
CGFloat r, g, b, a;
|
||||
CGColorRef cgColor = [self CGColor];
|
||||
const CGFloat *components = CGColorGetComponents(cgColor);
|
||||
if (CGColorGetNumberOfComponents(cgColor) == 4) {
|
||||
r = components[0];
|
||||
g = components[1];
|
||||
b = components[2];
|
||||
a = components[3];
|
||||
} else if (CGColorGetNumberOfComponents(cgColor) == 2) {
|
||||
r = components[0];
|
||||
g = components[0];
|
||||
b = components[0];
|
||||
a = components[1];
|
||||
} else if (CGColorGetNumberOfComponents(cgColor) == 1) {
|
||||
r = components[0];
|
||||
g = components[0];
|
||||
b = components[0];
|
||||
a = components[0];
|
||||
} else {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = 0;
|
||||
NSAssert(NO, @"");
|
||||
}
|
||||
NSArray<NSNumber *> *rgba = @[@(r), @(g), @(b), @(a)];
|
||||
return rgba;
|
||||
}
|
||||
|
||||
+ (instancetype)lks_colorFromRGBAComponents:(NSArray<NSNumber *> *)components {
|
||||
if (!components) {
|
||||
return nil;
|
||||
}
|
||||
if (components.count != 4) {
|
||||
NSAssert(NO, @"");
|
||||
return nil;
|
||||
}
|
||||
UIColor *color = [UIColor colorWithRed:components[0].doubleValue green:components[1].doubleValue blue:components[2].doubleValue alpha:components[3].doubleValue];
|
||||
return color;
|
||||
}
|
||||
|
||||
- (NSString *)lks_rgbaString {
|
||||
CGFloat r, g, b, a;
|
||||
CGColorRef cgColor = [self CGColor];
|
||||
const CGFloat *components = CGColorGetComponents(cgColor);
|
||||
if (CGColorGetNumberOfComponents(cgColor) == 4) {
|
||||
r = components[0];
|
||||
g = components[1];
|
||||
b = components[2];
|
||||
a = components[3];
|
||||
} else if (CGColorGetNumberOfComponents(cgColor) == 2) {
|
||||
r = components[0];
|
||||
g = components[0];
|
||||
b = components[0];
|
||||
a = components[1];
|
||||
} else {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = 0;
|
||||
NSAssert(NO, @"");
|
||||
}
|
||||
|
||||
if (a >= 1) {
|
||||
return [NSString stringWithFormat:@"(%.0f, %.0f, %.0f)", r * 255, g * 255, b * 255];
|
||||
} else {
|
||||
return [NSString stringWithFormat:@"(%.0f, %.0f, %.0f, %.2f)", r * 255, g * 255, b * 255, a];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)lks_hexString {
|
||||
CGFloat r, g, b, a;
|
||||
CGColorRef cgColor = [self CGColor];
|
||||
const CGFloat *components = CGColorGetComponents(cgColor);
|
||||
if (CGColorGetNumberOfComponents(cgColor) == 4) {
|
||||
r = components[0];
|
||||
g = components[1];
|
||||
b = components[2];
|
||||
a = components[3];
|
||||
} else if (CGColorGetNumberOfComponents(cgColor) == 2) {
|
||||
r = components[0];
|
||||
g = components[0];
|
||||
b = components[0];
|
||||
a = components[1];
|
||||
} else {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = 0;
|
||||
NSAssert(NO, @"");
|
||||
}
|
||||
|
||||
NSInteger red = r * 255;
|
||||
NSInteger green = g * 255;
|
||||
NSInteger blue = b * 255;
|
||||
NSInteger alpha = a * 255;
|
||||
|
||||
return [[NSString stringWithFormat:@"#%@%@%@%@",
|
||||
[UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:alpha]],
|
||||
[UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:red]],
|
||||
[UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:green]],
|
||||
[UIColor _alignColorHexStringLength:[UIColor _hexStringWithInteger:blue]]] lowercaseString];
|
||||
}
|
||||
|
||||
// 对于色值只有单位数的,在前面补一个0,例如“F”会补齐为“0F”
|
||||
+ (NSString *)_alignColorHexStringLength:(NSString *)hexString {
|
||||
return hexString.length < 2 ? [@"0" stringByAppendingString:hexString] : hexString;
|
||||
}
|
||||
|
||||
+ (NSString *)_hexStringWithInteger:(NSInteger)integer {
|
||||
NSString *hexString = @"";
|
||||
NSInteger remainder = 0;
|
||||
for (NSInteger i = 0; i < 9; i++) {
|
||||
remainder = integer % 16;
|
||||
integer = integer / 16;
|
||||
NSString *letter = [self _hexLetterStringWithInteger:remainder];
|
||||
hexString = [letter stringByAppendingString:hexString];
|
||||
if (integer == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return hexString;
|
||||
}
|
||||
|
||||
+ (NSString *)_hexLetterStringWithInteger:(NSInteger)integer {
|
||||
NSAssert(integer < 16, @"要转换的数必须是16进制里的个位数,也即小于16,但你传给我是%@", @(integer));
|
||||
|
||||
NSString *letter = nil;
|
||||
switch (integer) {
|
||||
case 10:
|
||||
letter = @"A";
|
||||
break;
|
||||
case 11:
|
||||
letter = @"B";
|
||||
break;
|
||||
case 12:
|
||||
letter = @"C";
|
||||
break;
|
||||
case 13:
|
||||
letter = @"D";
|
||||
break;
|
||||
case 14:
|
||||
letter = @"E";
|
||||
break;
|
||||
case 15:
|
||||
letter = @"F";
|
||||
break;
|
||||
default:
|
||||
letter = [[NSString alloc]initWithFormat:@"%@", @(integer)];
|
||||
break;
|
||||
}
|
||||
return letter;
|
||||
}
|
||||
|
||||
+ (UIColor *)lks_colorWithCGColor:(CGColorRef)cgColor {
|
||||
if (!cgColor) {
|
||||
return nil;
|
||||
}
|
||||
if (CFGetTypeID(cgColor) != CGColorGetTypeID()) {
|
||||
return nil;
|
||||
}
|
||||
return [UIColor colorWithCGColor:cgColor];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
22
Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.h
generated
Normal file
22
Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.h
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIImage+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/5/14.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIImage (LookinServer)
|
||||
|
||||
/// 该方法的实现需要 Hook,因此若定义了 LOOKIN_SERVER_DISABLE_HOOK 宏,则属性会返回 nil
|
||||
@property(nonatomic, copy) NSString *lks_imageSourceName;
|
||||
|
||||
- (NSData *)lookin_data;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
95
Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.m
generated
Normal file
95
Pods/LookinServer/Src/Main/Server/Category/UIImage+LookinServer.m
generated
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIImage+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/5/14.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import "UIImage+LookinServer.h"
|
||||
#import "LookinServerDefines.h"
|
||||
|
||||
@implementation UIImage (LookinServer)
|
||||
|
||||
#ifdef LOOKIN_SERVER_DISABLE_HOOK
|
||||
|
||||
- (void)setLks_imageSourceName:(NSString *)lks_imageSourceName {
|
||||
}
|
||||
|
||||
- (NSString *)lks_imageSourceName {
|
||||
return nil;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
+ (void)load {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
Method oriMethod = class_getClassMethod([self class], @selector(imageNamed:));
|
||||
Method newMethod = class_getClassMethod([self class], @selector(lks_imageNamed:));
|
||||
method_exchangeImplementations(oriMethod, newMethod);
|
||||
|
||||
oriMethod = class_getClassMethod([self class], @selector(imageWithContentsOfFile:));
|
||||
newMethod = class_getClassMethod([self class], @selector(lks_imageWithContentsOfFile:));
|
||||
method_exchangeImplementations(oriMethod, newMethod);
|
||||
|
||||
oriMethod = class_getClassMethod([self class], @selector(imageNamed:inBundle:compatibleWithTraitCollection:));
|
||||
newMethod = class_getClassMethod([self class], @selector(lks_imageNamed:inBundle:compatibleWithTraitCollection:));
|
||||
method_exchangeImplementations(oriMethod, newMethod);
|
||||
|
||||
if (@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)) {
|
||||
oriMethod = class_getClassMethod([self class], @selector(imageNamed:inBundle:withConfiguration:));
|
||||
newMethod = class_getClassMethod([self class], @selector(lks_imageNamed:inBundle:withConfiguration:));
|
||||
method_exchangeImplementations(oriMethod, newMethod);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+ (nullable UIImage *)lks_imageNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle withConfiguration:(nullable UIImageConfiguration *)configuration API_AVAILABLE(ios(13.0),tvos(13.0),watchos(6.0))
|
||||
{
|
||||
UIImage *image = [self lks_imageNamed:name inBundle:bundle withConfiguration:configuration];
|
||||
image.lks_imageSourceName = name;
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (nullable UIImage *)lks_imageNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection API_AVAILABLE(ios(8.0))
|
||||
{
|
||||
UIImage *image = [self lks_imageNamed:name inBundle:bundle compatibleWithTraitCollection:traitCollection];
|
||||
image.lks_imageSourceName = name;
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (UIImage *)lks_imageNamed:(NSString *)name {
|
||||
UIImage *image = [self lks_imageNamed:name];
|
||||
image.lks_imageSourceName = name;
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (UIImage *)lks_imageWithContentsOfFile:(NSString *)path {
|
||||
UIImage *image = [self lks_imageWithContentsOfFile:path];
|
||||
|
||||
NSString *fileName = [[path componentsSeparatedByString:@"/"].lastObject componentsSeparatedByString:@"."].firstObject;
|
||||
image.lks_imageSourceName = fileName;
|
||||
return image;
|
||||
}
|
||||
|
||||
- (void)setLks_imageSourceName:(NSString *)lks_imageSourceName {
|
||||
[self lookin_bindObject:lks_imageSourceName.copy forKey:@"lks_imageSourceName"];
|
||||
}
|
||||
|
||||
- (NSString *)lks_imageSourceName {
|
||||
return [self lookin_getBindObjectForKey:@"lks_imageSourceName"];
|
||||
}
|
||||
|
||||
#endif /* LOOKIN_SERVER_DISABLE_HOOK */
|
||||
|
||||
- (NSData *)lookin_data {
|
||||
return UIImagePNGRepresentation(self);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
20
Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.h
generated
Normal file
20
Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.h
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIImageView+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/9/18.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIImageView (LookinServer)
|
||||
|
||||
- (NSString *)lks_imageSourceName;
|
||||
- (NSNumber *)lks_imageViewOidIfHasImage;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
31
Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.m
generated
Normal file
31
Pods/LookinServer/Src/Main/Server/Category/UIImageView+LookinServer.m
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIImageView+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/9/18.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UIImageView+LookinServer.h"
|
||||
#import "UIImage+LookinServer.h"
|
||||
#import "NSObject+LookinServer.h"
|
||||
|
||||
@implementation UIImageView (LookinServer)
|
||||
|
||||
- (NSString *)lks_imageSourceName {
|
||||
return self.image.lks_imageSourceName;
|
||||
}
|
||||
|
||||
- (NSNumber *)lks_imageViewOidIfHasImage {
|
||||
if (!self.image) {
|
||||
return nil;
|
||||
}
|
||||
unsigned long oid = [self lks_registerOid];
|
||||
return @(oid);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
21
Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.h
generated
Normal file
21
Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UILabel+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/2/26.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UILabel (LookinServer)
|
||||
|
||||
@property(nonatomic, assign) CGFloat lks_fontSize;
|
||||
|
||||
- (NSString *)lks_fontName;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
29
Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.m
generated
Normal file
29
Pods/LookinServer/Src/Main/Server/Category/UILabel+LookinServer.m
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UILabel+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/2/26.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UILabel+LookinServer.h"
|
||||
|
||||
@implementation UILabel (LookinServer)
|
||||
|
||||
- (CGFloat)lks_fontSize {
|
||||
return self.font.pointSize;
|
||||
}
|
||||
- (void)setLks_fontSize:(CGFloat)lks_fontSize {
|
||||
UIFont *font = [self.font fontWithSize:lks_fontSize];
|
||||
self.font = font;
|
||||
}
|
||||
|
||||
- (NSString *)lks_fontName {
|
||||
return self.font.fontName;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
19
Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.h
generated
Normal file
19
Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.h
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UITableView+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/9/5.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UITableView (LookinServer)
|
||||
|
||||
- (NSArray<NSNumber *> *)lks_numberOfRows;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
29
Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.m
generated
Normal file
29
Pods/LookinServer/Src/Main/Server/Category/UITableView+LookinServer.m
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UITableView+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/9/5.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UITableView+LookinServer.h"
|
||||
#import "LookinServerDefines.h"
|
||||
|
||||
@implementation UITableView (LookinServer)
|
||||
|
||||
- (NSArray<NSNumber *> *)lks_numberOfRows {
|
||||
NSUInteger sectionsCount = MIN(self.numberOfSections, 10);
|
||||
NSArray<NSNumber *> *rowsCount = [NSArray lookin_arrayWithCount:sectionsCount block:^id(NSUInteger idx) {
|
||||
return @([self numberOfRowsInSection:idx]);
|
||||
}];
|
||||
if (rowsCount.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
return rowsCount;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
21
Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.h
generated
Normal file
21
Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UITextField+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/2/26.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UITextField (LookinServer)
|
||||
|
||||
@property(nonatomic, assign) CGFloat lks_fontSize;
|
||||
|
||||
- (NSString *)lks_fontName;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
29
Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.m
generated
Normal file
29
Pods/LookinServer/Src/Main/Server/Category/UITextField+LookinServer.m
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UITextField+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/2/26.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UITextField+LookinServer.h"
|
||||
|
||||
@implementation UITextField (LookinServer)
|
||||
|
||||
- (CGFloat)lks_fontSize {
|
||||
return self.font.pointSize;
|
||||
}
|
||||
- (void)setLks_fontSize:(CGFloat)lks_fontSize {
|
||||
UIFont *font = [self.font fontWithSize:lks_fontSize];
|
||||
self.font = font;
|
||||
}
|
||||
|
||||
- (NSString *)lks_fontName {
|
||||
return self.font.fontName;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
21
Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.h
generated
Normal file
21
Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UITextView+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/2/26.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UITextView (LookinServer)
|
||||
|
||||
@property(nonatomic, assign) CGFloat lks_fontSize;
|
||||
|
||||
- (NSString *)lks_fontName;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
29
Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.m
generated
Normal file
29
Pods/LookinServer/Src/Main/Server/Category/UITextView+LookinServer.m
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UITextView+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/2/26.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UITextView+LookinServer.h"
|
||||
|
||||
@implementation UITextView (LookinServer)
|
||||
|
||||
- (CGFloat)lks_fontSize {
|
||||
return self.font.pointSize;
|
||||
}
|
||||
- (void)setLks_fontSize:(CGFloat)lks_fontSize {
|
||||
UIFont *font = [self.font fontWithSize:lks_fontSize];
|
||||
self.font = font;
|
||||
}
|
||||
|
||||
- (NSString *)lks_fontName {
|
||||
return self.font.fontName;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
44
Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.h
generated
Normal file
44
Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.h
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIView+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/3/19.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "LookinDefines.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIView (LookinServer)
|
||||
|
||||
/// 如果 myViewController.view = myView,则可以通过 myView 的 lks_findHostViewController 方法找到 myViewController
|
||||
- (UIViewController *)lks_findHostViewController;
|
||||
|
||||
/// 是否是 UITabBar 的 childrenView,如果是的话,则截图时需要强制使用 renderInContext: 的方式而非 drawViewHierarchyInRect:afterScreenUpdates: 否则在 iOS 13 上获取到的图像是空的不知道为什么
|
||||
@property(nonatomic, assign) BOOL lks_isChildrenViewOfTabBar;
|
||||
|
||||
/// point 是相对于 receiver 自身的坐标系
|
||||
- (UIView *)lks_subviewAtPoint:(CGPoint)point preferredClasses:(NSArray<Class> *)preferredClasses;
|
||||
|
||||
- (CGFloat)lks_bestWidth;
|
||||
- (CGFloat)lks_bestHeight;
|
||||
- (CGSize)lks_bestSize;
|
||||
|
||||
@property(nonatomic, assign) float lks_horizontalContentHuggingPriority;
|
||||
@property(nonatomic, assign) float lks_verticalContentHuggingPriority;
|
||||
|
||||
@property(nonatomic, assign) float lks_horizontalContentCompressionResistancePriority;
|
||||
@property(nonatomic, assign) float lks_verticalContentCompressionResistancePriority;
|
||||
|
||||
/// 遍历全局的 view 并给他们设置 lks_involvedRawConstraints 属性
|
||||
+ (void)lks_rebuildGlobalInvolvedRawConstraints;
|
||||
/// 该属性保存了牵扯到当前 view 的所有 constraints,包括那些没有生效的
|
||||
@property(nonatomic, strong) NSMutableArray<NSLayoutConstraint *> *lks_involvedRawConstraints;
|
||||
|
||||
- (NSArray<NSDictionary<NSString *, id> *> *)lks_constraints;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
215
Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.m
generated
Normal file
215
Pods/LookinServer/Src/Main/Server/Category/UIView+LookinServer.m
generated
Normal file
@@ -0,0 +1,215 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIView+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/3/19.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UIView+LookinServer.h"
|
||||
#import <objc/runtime.h>
|
||||
#import "LookinObject.h"
|
||||
#import "LookinAutoLayoutConstraint.h"
|
||||
#import "LookinServerDefines.h"
|
||||
#import "LKS_MultiplatformAdapter.h"
|
||||
|
||||
@implementation UIView (LookinServer)
|
||||
|
||||
- (UIViewController *)lks_findHostViewController {
|
||||
UIResponder *responder = [self nextResponder];
|
||||
if (!responder) {
|
||||
return nil;
|
||||
}
|
||||
if (![responder isKindOfClass:[UIViewController class]]) {
|
||||
return nil;
|
||||
}
|
||||
UIViewController *viewController = (UIViewController *)responder;
|
||||
if (viewController.view != self) {
|
||||
return nil;
|
||||
}
|
||||
return viewController;
|
||||
}
|
||||
|
||||
- (UIView *)lks_subviewAtPoint:(CGPoint)point preferredClasses:(NSArray<Class> *)preferredClasses {
|
||||
BOOL isPreferredClassForSelf = [preferredClasses lookin_any:^BOOL(Class obj) {
|
||||
return [self isKindOfClass:obj];
|
||||
}];
|
||||
if (isPreferredClassForSelf) {
|
||||
return self;
|
||||
}
|
||||
|
||||
UIView *targetView = [self.subviews lookin_lastFiltered:^BOOL(__kindof UIView *obj) {
|
||||
if (obj.hidden || obj.alpha <= 0.01) {
|
||||
return NO;
|
||||
}
|
||||
BOOL contains = CGRectContainsPoint(obj.frame, point);
|
||||
return contains;
|
||||
}];
|
||||
|
||||
if (!targetView) {
|
||||
return self;
|
||||
}
|
||||
|
||||
CGPoint newPoint = [targetView convertPoint:point fromView:self];
|
||||
targetView = [targetView lks_subviewAtPoint:newPoint preferredClasses:preferredClasses];
|
||||
return targetView;
|
||||
}
|
||||
|
||||
- (CGSize)lks_bestSize {
|
||||
return [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||
}
|
||||
|
||||
- (CGFloat)lks_bestWidth {
|
||||
return self.lks_bestSize.width;
|
||||
}
|
||||
|
||||
- (CGFloat)lks_bestHeight {
|
||||
return self.lks_bestSize.height;
|
||||
}
|
||||
|
||||
- (void)setLks_isChildrenViewOfTabBar:(BOOL)lks_isChildrenViewOfTabBar {
|
||||
[self lookin_bindBOOL:lks_isChildrenViewOfTabBar forKey:@"lks_isChildrenViewOfTabBar"];
|
||||
}
|
||||
- (BOOL)lks_isChildrenViewOfTabBar {
|
||||
return [self lookin_getBindBOOLForKey:@"lks_isChildrenViewOfTabBar"];
|
||||
}
|
||||
|
||||
- (void)setLks_verticalContentHuggingPriority:(float)lks_verticalContentHuggingPriority {
|
||||
[self setContentHuggingPriority:lks_verticalContentHuggingPriority forAxis:UILayoutConstraintAxisVertical];
|
||||
}
|
||||
- (float)lks_verticalContentHuggingPriority {
|
||||
return [self contentHuggingPriorityForAxis:UILayoutConstraintAxisVertical];
|
||||
}
|
||||
|
||||
- (void)setLks_horizontalContentHuggingPriority:(float)lks_horizontalContentHuggingPriority {
|
||||
[self setContentHuggingPriority:lks_horizontalContentHuggingPriority forAxis:UILayoutConstraintAxisHorizontal];
|
||||
}
|
||||
- (float)lks_horizontalContentHuggingPriority {
|
||||
return [self contentHuggingPriorityForAxis:UILayoutConstraintAxisHorizontal];
|
||||
}
|
||||
|
||||
- (void)setLks_verticalContentCompressionResistancePriority:(float)lks_verticalContentCompressionResistancePriority {
|
||||
[self setContentCompressionResistancePriority:lks_verticalContentCompressionResistancePriority forAxis:UILayoutConstraintAxisVertical];
|
||||
}
|
||||
- (float)lks_verticalContentCompressionResistancePriority {
|
||||
return [self contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisVertical];
|
||||
}
|
||||
|
||||
- (void)setLks_horizontalContentCompressionResistancePriority:(float)lks_horizontalContentCompressionResistancePriority {
|
||||
[self setContentCompressionResistancePriority:lks_horizontalContentCompressionResistancePriority forAxis:UILayoutConstraintAxisHorizontal];
|
||||
}
|
||||
- (float)lks_horizontalContentCompressionResistancePriority {
|
||||
return [self contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisHorizontal];
|
||||
}
|
||||
|
||||
+ (void)lks_rebuildGlobalInvolvedRawConstraints {
|
||||
[[LKS_MultiplatformAdapter allWindows] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
[self lks_removeInvolvedRawConstraintsForViewsRootedByView:window];
|
||||
}];
|
||||
[[LKS_MultiplatformAdapter allWindows] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
[self lks_addInvolvedRawConstraintsForViewsRootedByView:window];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)lks_addInvolvedRawConstraintsForViewsRootedByView:(UIView *)rootView {
|
||||
[rootView.constraints enumerateObjectsUsingBlock:^(__kindof NSLayoutConstraint * _Nonnull constraint, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
UIView *firstView = constraint.firstItem;
|
||||
if ([firstView isKindOfClass:[UIView class]] && ![firstView.lks_involvedRawConstraints containsObject:constraint]) {
|
||||
if (!firstView.lks_involvedRawConstraints) {
|
||||
firstView.lks_involvedRawConstraints = [NSMutableArray array];
|
||||
}
|
||||
[firstView.lks_involvedRawConstraints addObject:constraint];
|
||||
}
|
||||
|
||||
UIView *secondView = constraint.secondItem;
|
||||
if ([secondView isKindOfClass:[UIView class]] && ![secondView.lks_involvedRawConstraints containsObject:constraint]) {
|
||||
if (!secondView.lks_involvedRawConstraints) {
|
||||
secondView.lks_involvedRawConstraints = [NSMutableArray array];
|
||||
}
|
||||
[secondView.lks_involvedRawConstraints addObject:constraint];
|
||||
}
|
||||
}];
|
||||
|
||||
[rootView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
[self lks_addInvolvedRawConstraintsForViewsRootedByView:subview];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)lks_removeInvolvedRawConstraintsForViewsRootedByView:(UIView *)rootView {
|
||||
[rootView.lks_involvedRawConstraints removeAllObjects];
|
||||
[rootView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
[self lks_removeInvolvedRawConstraintsForViewsRootedByView:subview];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setLks_involvedRawConstraints:(NSMutableArray<NSLayoutConstraint *> *)lks_involvedRawConstraints {
|
||||
[self lookin_bindObject:lks_involvedRawConstraints forKey:@"lks_involvedRawConstraints"];
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSLayoutConstraint *> *)lks_involvedRawConstraints {
|
||||
return [self lookin_getBindObjectForKey:@"lks_involvedRawConstraints"];
|
||||
}
|
||||
|
||||
- (NSArray<LookinAutoLayoutConstraint *> *)lks_constraints {
|
||||
/**
|
||||
- lks_involvedRawConstraints 保存了牵扯到了 self 的所有的 constraints(包括未生效的,但不包括 inactive 的,整个产品逻辑都是直接忽略 inactive 的 constraints)
|
||||
- 通过 constraintsAffectingLayoutForAxis 可以拿到会影响 self 布局的所有已生效的 constraints(这里称之为 effectiveConstraints)
|
||||
- 很多情况下,一条 constraint 会出现在 effectiveConstraints 里但不会出现在 lks_involvedRawConstraints 里,比如:
|
||||
· UIWindow 拥有 minX, minY, width, height 四个 effectiveConstraints,但 lks_involvedRawConstraints 为空,因为它的 constraints 属性为空(这一点不知道为啥,但 Xcode Inspector 和 Reveal 确实也不会显示这四个 constraints)
|
||||
· 如果设置了 View1 的 center 和 superview 的 center 保持一致,则 superview 的 width 和 height 也会出现在 effectiveConstraints 里,但不会出现在 lks_involvedRawConstraints 里(这点可以理解,毕竟这种场景下 superview 的 width 和 height 确实会影响到 View1)
|
||||
*/
|
||||
NSMutableArray<NSLayoutConstraint *> *effectiveConstraints = [NSMutableArray array];
|
||||
[effectiveConstraints addObjectsFromArray:[self constraintsAffectingLayoutForAxis:UILayoutConstraintAxisHorizontal]];
|
||||
[effectiveConstraints addObjectsFromArray:[self constraintsAffectingLayoutForAxis:UILayoutConstraintAxisVertical]];
|
||||
|
||||
NSArray<LookinAutoLayoutConstraint *> *lookinConstraints = [self.lks_involvedRawConstraints lookin_map:^id(NSUInteger idx, __kindof NSLayoutConstraint *constraint) {
|
||||
BOOL isEffective = [effectiveConstraints containsObject:constraint];
|
||||
if ([constraint isActive]) {
|
||||
// trying to get firstItem or secondItem of an inactive constraint may cause dangling-pointer crash
|
||||
// https://github.com/QMUI/LookinServer/issues/86
|
||||
LookinConstraintItemType firstItemType = [self _lks_constraintItemTypeForItem:constraint.firstItem];
|
||||
LookinConstraintItemType secondItemType = [self _lks_constraintItemTypeForItem:constraint.secondItem];
|
||||
LookinAutoLayoutConstraint *lookinConstraint = [LookinAutoLayoutConstraint instanceFromNSConstraint:constraint isEffective:isEffective firstItemType:firstItemType secondItemType:secondItemType];
|
||||
return lookinConstraint;
|
||||
}
|
||||
return nil;
|
||||
}];
|
||||
return lookinConstraints.count ? lookinConstraints : nil;
|
||||
}
|
||||
|
||||
- (LookinConstraintItemType)_lks_constraintItemTypeForItem:(id)item {
|
||||
if (!item) {
|
||||
return LookinConstraintItemTypeNil;
|
||||
}
|
||||
if (item == self) {
|
||||
return LookinConstraintItemTypeSelf;
|
||||
}
|
||||
if (item == self.superview) {
|
||||
return LookinConstraintItemTypeSuper;
|
||||
}
|
||||
|
||||
// 在 runtime 时,这里会遇到的 UILayoutGuide 和 _UILayoutGuide 居然是 UIView 的子类,不知道是看错了还是有什么玄机,所以在判断是否是 UIView 之前要先判断这个
|
||||
if (@available(iOS 9.0, *)) {
|
||||
if ([item isKindOfClass:[UILayoutGuide class]]) {
|
||||
return LookinConstraintItemTypeLayoutGuide;
|
||||
}
|
||||
}
|
||||
|
||||
NSString *className = NSStringFromClass([item class]);
|
||||
if ([className hasSuffix:@"_UILayoutGuide"]) {
|
||||
return LookinConstraintItemTypeLayoutGuide;
|
||||
}
|
||||
|
||||
if ([item isKindOfClass:[UIView class]]) {
|
||||
return LookinConstraintItemTypeView;
|
||||
}
|
||||
|
||||
NSAssert(NO, @"");
|
||||
return LookinConstraintItemTypeUnknown;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
19
Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.h
generated
Normal file
19
Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.h
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIViewController+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/4/22.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIViewController (LookinServer)
|
||||
|
||||
+ (UIViewController *)lks_visibleViewController;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
48
Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.m
generated
Normal file
48
Pods/LookinServer/Src/Main/Server/Category/UIViewController+LookinServer.m
generated
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIViewController+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/4/22.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UIViewController+LookinServer.h"
|
||||
#import "UIView+LookinServer.h"
|
||||
#import <objc/runtime.h>
|
||||
#import "LKS_MultiplatformAdapter.h"
|
||||
|
||||
@implementation UIViewController (LookinServer)
|
||||
|
||||
+ (nullable UIViewController *)lks_visibleViewController {
|
||||
|
||||
UIViewController *rootViewController = [LKS_MultiplatformAdapter keyWindow].rootViewController;
|
||||
UIViewController *visibleViewController = [rootViewController lks_visibleViewControllerIfExist];
|
||||
return visibleViewController;
|
||||
}
|
||||
|
||||
- (UIViewController *)lks_visibleViewControllerIfExist {
|
||||
|
||||
if (self.presentedViewController) {
|
||||
return [self.presentedViewController lks_visibleViewControllerIfExist];
|
||||
}
|
||||
|
||||
if ([self isKindOfClass:[UINavigationController class]]) {
|
||||
return [((UINavigationController *)self).visibleViewController lks_visibleViewControllerIfExist];
|
||||
}
|
||||
|
||||
if ([self isKindOfClass:[UITabBarController class]]) {
|
||||
return [((UITabBarController *)self).selectedViewController lks_visibleViewControllerIfExist];
|
||||
}
|
||||
|
||||
if (self.isViewLoaded && !self.view.hidden && self.view.alpha > 0.01) {
|
||||
return self;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
21
Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.h
generated
Normal file
21
Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIVisualEffectView+LookinServer.h
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/10/8.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIVisualEffectView (LookinServer)
|
||||
|
||||
- (void)setLks_blurEffectStyleNumber:(NSNumber *)lks_blurEffectStyleNumber;
|
||||
|
||||
- (NSNumber *)lks_blurEffectStyleNumber;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
33
Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.m
generated
Normal file
33
Pods/LookinServer/Src/Main/Server/Category/UIVisualEffectView+LookinServer.m
generated
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifdef SHOULD_COMPILE_LOOKIN_SERVER
|
||||
|
||||
//
|
||||
// UIVisualEffectView+LookinServer.m
|
||||
// LookinServer
|
||||
//
|
||||
// Created by Li Kai on 2019/10/8.
|
||||
// https://lookin.work
|
||||
//
|
||||
|
||||
#import "UIVisualEffectView+LookinServer.h"
|
||||
#import "UIBlurEffect+LookinServer.h"
|
||||
|
||||
@implementation UIVisualEffectView (LookinServer)
|
||||
|
||||
- (void)setLks_blurEffectStyleNumber:(NSNumber *)lks_blurEffectStyleNumber {
|
||||
UIBlurEffectStyle style = [lks_blurEffectStyleNumber integerValue];
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:style];
|
||||
self.effect = effect;
|
||||
}
|
||||
|
||||
- (NSNumber *)lks_blurEffectStyleNumber {
|
||||
UIVisualEffect *effect = self.effect;
|
||||
if (![effect isKindOfClass:[UIBlurEffect class]]) {
|
||||
return nil;
|
||||
}
|
||||
UIBlurEffect *blurEffect = (UIBlurEffect *)effect;
|
||||
return blurEffect.lks_effectStyleNumber;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|
||||
Reference in New Issue
Block a user