Skip to content

Commit

Permalink
0.2.9
Browse files Browse the repository at this point in the history
  • Loading branch information
CloudlessMoon committed Oct 16, 2024
1 parent 6368c5b commit 2a5873d
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 101 deletions.
7 changes: 2 additions & 5 deletions Example/Podfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
platform :ios, "12.0"
use_frameworks! :linkage => :static

source "https://github.com/CocoaPods/Specs.git"

def pod_Common
pod "JSCoreKit", :path => ".."
end

target "JSCoreKitExample" do
pod_Common
pod "LookinServer", "~> 1.0.4", :configurations => ["Debug"]
pod "MLeaksFinder", :configurations => ["Debug"]
pod "FBRetainCycleDetector", :git => "https://github.com/jiasongs/FBRetainCycleDetector.git", :configurations => ["Debug"]
pod "LookinServer", :configurations => ["Debug"]
pod "MLeaksFinder", :git => "https://github.com/Tencent/MLeaksFinder.git", :configurations => ["Debug"]
end
2 changes: 1 addition & 1 deletion JSCoreKit.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Pod::Spec.new do |s|
s.name = "JSCoreKit"
s.version = "0.2.8"
s.version = "0.2.9"
s.summary = "JSCoreKit"
s.homepage = "https://github.com/jiasongs/JSCoreKit"
s.author = { "jiasong" => "[email protected]" }
Expand Down
104 changes: 48 additions & 56 deletions Sources/Extension/UIKit/CALayer+JSCore.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,65 +11,57 @@
@implementation CALayer (JSCore)

- (void)js_removeDefaultAnimations {
static NSMutableDictionary<NSString *, id<CAAction>> *actions = nil;
static NSDictionary<NSString *, id<CAAction>> *actions = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
actions = @{NSStringFromSelector(@selector(bounds)): [NSNull null],
NSStringFromSelector(@selector(position)): [NSNull null],
NSStringFromSelector(@selector(zPosition)): [NSNull null],
NSStringFromSelector(@selector(anchorPoint)): [NSNull null],
NSStringFromSelector(@selector(anchorPointZ)): [NSNull null],
NSStringFromSelector(@selector(transform)): [NSNull null],
JSBeginIgnoreClangWarning(-Wundeclared-selector)
NSStringFromSelector(@selector(hidden)): [NSNull null],
NSStringFromSelector(@selector(doubleSided)): [NSNull null],
JSEndIgnoreClangWarning
NSStringFromSelector(@selector(sublayerTransform)): [NSNull null],
NSStringFromSelector(@selector(masksToBounds)): [NSNull null],
NSStringFromSelector(@selector(contents)): [NSNull null],
NSStringFromSelector(@selector(contentsRect)): [NSNull null],
NSStringFromSelector(@selector(contentsScale)): [NSNull null],
NSStringFromSelector(@selector(contentsCenter)): [NSNull null],
NSStringFromSelector(@selector(minificationFilterBias)): [NSNull null],
NSStringFromSelector(@selector(backgroundColor)): [NSNull null],
NSStringFromSelector(@selector(cornerRadius)): [NSNull null],
NSStringFromSelector(@selector(borderWidth)): [NSNull null],
NSStringFromSelector(@selector(borderColor)): [NSNull null],
NSStringFromSelector(@selector(opacity)): [NSNull null],
NSStringFromSelector(@selector(compositingFilter)): [NSNull null],
NSStringFromSelector(@selector(filters)): [NSNull null],
NSStringFromSelector(@selector(backgroundFilters)): [NSNull null],
NSStringFromSelector(@selector(shouldRasterize)): [NSNull null],
NSStringFromSelector(@selector(rasterizationScale)): [NSNull null],
NSStringFromSelector(@selector(shadowColor)): [NSNull null],
NSStringFromSelector(@selector(shadowOpacity)): [NSNull null],
NSStringFromSelector(@selector(shadowOffset)): [NSNull null],
NSStringFromSelector(@selector(shadowRadius)): [NSNull null],
NSStringFromSelector(@selector(shadowPath)): [NSNull null]}.mutableCopy;

if (@available(iOS 11.0, *)) {
[actions addEntriesFromDictionary:@{NSStringFromSelector(@selector(maskedCorners)): [NSNull null]}];
}

if ([self isKindOfClass:[CAShapeLayer class]]) {
[actions addEntriesFromDictionary:@{NSStringFromSelector(@selector(path)): [NSNull null],
NSStringFromSelector(@selector(fillColor)): [NSNull null],
NSStringFromSelector(@selector(strokeColor)): [NSNull null],
NSStringFromSelector(@selector(strokeStart)): [NSNull null],
NSStringFromSelector(@selector(strokeEnd)): [NSNull null],
NSStringFromSelector(@selector(lineWidth)): [NSNull null],
NSStringFromSelector(@selector(miterLimit)): [NSNull null],
NSStringFromSelector(@selector(lineDashPhase)): [NSNull null]}];
}

if ([self isKindOfClass:[CAGradientLayer class]]) {
[actions addEntriesFromDictionary:@{NSStringFromSelector(@selector(colors)): [NSNull null],
NSStringFromSelector(@selector(locations)): [NSNull null],
NSStringFromSelector(@selector(startPoint)): [NSNull null],
NSStringFromSelector(@selector(endPoint)): [NSNull null]}];
}
actions = @{
NSStringFromSelector(@selector(bounds)): [NSNull null],
NSStringFromSelector(@selector(position)): [NSNull null],
NSStringFromSelector(@selector(zPosition)): [NSNull null],
NSStringFromSelector(@selector(anchorPoint)): [NSNull null],
NSStringFromSelector(@selector(anchorPointZ)): [NSNull null],
NSStringFromSelector(@selector(transform)): [NSNull null],
JSBeginIgnoreClangWarning(-Wundeclared-selector)
NSStringFromSelector(@selector(hidden)): [NSNull null],
NSStringFromSelector(@selector(doubleSided)): [NSNull null],
JSEndIgnoreClangWarning
NSStringFromSelector(@selector(sublayerTransform)): [NSNull null],
NSStringFromSelector(@selector(masksToBounds)): [NSNull null],
NSStringFromSelector(@selector(contents)): [NSNull null],
NSStringFromSelector(@selector(contentsRect)): [NSNull null],
NSStringFromSelector(@selector(contentsScale)): [NSNull null],
NSStringFromSelector(@selector(contentsCenter)): [NSNull null],
NSStringFromSelector(@selector(minificationFilterBias)): [NSNull null],
NSStringFromSelector(@selector(backgroundColor)): [NSNull null],
NSStringFromSelector(@selector(cornerRadius)): [NSNull null],
NSStringFromSelector(@selector(borderWidth)): [NSNull null],
NSStringFromSelector(@selector(borderColor)): [NSNull null],
NSStringFromSelector(@selector(opacity)): [NSNull null],
NSStringFromSelector(@selector(compositingFilter)): [NSNull null],
NSStringFromSelector(@selector(filters)): [NSNull null],
NSStringFromSelector(@selector(backgroundFilters)): [NSNull null],
NSStringFromSelector(@selector(shouldRasterize)): [NSNull null],
NSStringFromSelector(@selector(rasterizationScale)): [NSNull null],
NSStringFromSelector(@selector(shadowColor)): [NSNull null],
NSStringFromSelector(@selector(shadowOpacity)): [NSNull null],
NSStringFromSelector(@selector(shadowOffset)): [NSNull null],
NSStringFromSelector(@selector(shadowRadius)): [NSNull null],
NSStringFromSelector(@selector(shadowPath)): [NSNull null],
NSStringFromSelector(@selector(maskedCorners)): [NSNull null],
NSStringFromSelector(@selector(path)): [NSNull null],
NSStringFromSelector(@selector(fillColor)): [NSNull null],
NSStringFromSelector(@selector(strokeColor)): [NSNull null],
NSStringFromSelector(@selector(strokeStart)): [NSNull null],
NSStringFromSelector(@selector(strokeEnd)): [NSNull null],
NSStringFromSelector(@selector(lineWidth)): [NSNull null],
NSStringFromSelector(@selector(miterLimit)): [NSNull null],
NSStringFromSelector(@selector(lineDashPhase)): [NSNull null],
NSStringFromSelector(@selector(colors)): [NSNull null],
NSStringFromSelector(@selector(locations)): [NSNull null],
NSStringFromSelector(@selector(startPoint)): [NSNull null],
NSStringFromSelector(@selector(endPoint)): [NSNull null]
};
});

self.actions = actions;
}

Expand Down
27 changes: 9 additions & 18 deletions Sources/Extension/UIKit/UIScrollView+JSCore.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,22 @@ - (CGPoint)js_minimumContentOffset {
}

- (CGPoint)js_maximumContentOffset {
if (self.js_canScroll) {
return CGPointMake(self.contentSize.width - self.js_width + self.adjustedContentInset.right,
self.contentSize.height - self.js_height + self.adjustedContentInset.bottom);
} else {
return CGPointMake(-self.adjustedContentInset.left, -self.adjustedContentInset.top);
}
CGPoint minimum = self.js_minimumContentOffset;
CGPoint maximum = CGPointMake(self.contentSize.width - CGRectGetWidth(self.bounds) + self.adjustedContentInset.right,
self.contentSize.height - CGRectGetHeight(self.bounds) + self.adjustedContentInset.bottom);
return CGPointMake(MAX(minimum.x, maximum.x), MAX(minimum.y, maximum.y));
}

- (void)js_scrollToOffset:(CGPoint)offset animated:(BOOL)animated {
if (!self.js_canScroll) {
return;
}

if (!CGPointEqualToPoint(self.contentOffset, offset)) {
CGRect maxRect = CGRectMake(-self.adjustedContentInset.left,
-self.adjustedContentInset.top,
self.contentSize.width - self.js_width + self.adjustedContentInset.right + self.adjustedContentInset.left,
self.contentSize.height - self.js_height + self.adjustedContentInset.bottom + self.adjustedContentInset.top);
if (!CGRectContainsPoint(maxRect, offset)) {
CGFloat x = MIN(MAX(offset.x, CGRectGetMinX(maxRect)), CGRectGetMaxX(maxRect));
CGFloat y = MIN(MAX(offset.y, CGRectGetMinY(maxRect)), CGRectGetMaxY(maxRect));
offset = CGPointMake(x, y);
}
[self setContentOffset:offset animated:animated];
}
CGPoint minimumOffset = self.js_minimumContentOffset;
CGPoint maximumOffset = self.js_maximumContentOffset;
CGFloat x = MIN(MAX(offset.x, minimumOffset.x), maximumOffset.x);
CGFloat y = MIN(MAX(offset.y, minimumOffset.y), maximumOffset.y);
[self setContentOffset:CGPointMake(x, y) animated:animated];
}

@end
2 changes: 2 additions & 0 deletions Sources/JSCoreKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#import <JSCoreKit/JSCoreHelper.h>
#import <JSCoreKit/JSCoreHelper+Animation.h>
#import <JSCoreKit/JSCoreHelper+Device.h>
#import <JSCoreKit/JSCoreHelper+LayoutGuide.h>

#else

Expand All @@ -34,6 +35,7 @@
#import "JSCoreHelper.h"
#import "JSCoreHelper+Animation.h"
#import "JSCoreHelper+Device.h"
#import "JSCoreHelper+LayoutGuide.h"

#endif /* __has_include */

Expand Down
15 changes: 1 addition & 14 deletions Sources/Main/JSCoreHelper+Animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,11 @@ typedef NS_ENUM(NSInteger, JSCoreAnimationExtrapolateType) {
scaleX:(CGFloat)scaleX
scaleY:(CGFloat)scaleY;

/// Convert radians to degrees.
+ (CGFloat)radiansToDegrees:(CGFloat)radians;

/// Convert degrees to radians.
+ (CGFloat)degreesToRadians:(CGFloat)degrees;

/**
类似系统 UIScrollView 在拖拽到内容尽头时会越拖越难拖的效果。
@param fromValue 初始值,一般为 0。
@param toValue 目标值,也即你希望拖拽到的极限距离。
@param time 当前拖拽距离相对于极限距离的百分比,0 表示在 fromValue,1 表示拖拽到与极限距离相同的大小,大于1表示拖拽得比极限距离还远。
@param coeff 取值范围-1~+∞。值越大,拖拽的初期越容易拖动。例如 0.1 表示从头到尾都很难拖动,9表示一开始稍微拖一下就可以动很长距离(也可以理解为只需要很短的拖拽动作就可以很快接近极限距离)。-1 表示用默认的 0.55,也即系统的 UIScrollView 的系数。
@return 返回当前 time 对应的移动距离,返回值大于等于 fromValue,小于 toValue(只会无限接近,不可能等于)。
*/
+ (CGFloat)bounceFromValue:(CGFloat)fromValue
toValue:(CGFloat)toValue
time:(CGFloat)time
coeff:(CGFloat)coeff;
+ (CGFloat)bounceFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue time:(CGFloat)time coeff:(CGFloat)coeff;

@end

Expand Down
2 changes: 1 addition & 1 deletion Sources/Main/JSCoreHelper+Animation.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ + (CGFloat)bounceFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue time:(CGF
CGFloat d = toValue;
CGFloat x = (d - fromValue) * time;
CGFloat result = fromValue + d + 1.0 - (1.0 / (coeff * x / d + 1)) * d;
// NSLog(@"[%.2f-%.2f], coeff = %.2f, x = %.2f, result = %.2f", fromValue, d, coeff, x, result);
// NSLog(@"[%.2f-%.2f], coeff = %.2f, x = %.2f, result = %.2f", fromValue, d, coeff, x, result);
return result;
}

Expand Down
1 change: 1 addition & 0 deletions Sources/Main/JSCoreHelper+Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (class, nonatomic, readonly) BOOL isMac;
@property (class, nonatomic, readonly) BOOL isMacCatalystApp;
@property (class, nonatomic, readonly) BOOL isiOSAppOnMac;
@property (class, nonatomic, readonly) BOOL isiOSAppOnVision NS_UNAVAILABLE; // Apple未开放相关API

@property (class, nonatomic, readonly) BOOL isIPad;
@property (class, nonatomic, readonly) BOOL isIPod;
Expand Down
22 changes: 16 additions & 6 deletions Sources/Main/JSCoreHelper+Device.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ + (BOOL)isMac {
}

+ (BOOL)isMacCatalystApp {
static BOOL isMacCatalystApp;
static BOOL isMacCatalystApp = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (@available(iOS 13.0, *)) {
Expand All @@ -25,7 +25,7 @@ + (BOOL)isMacCatalystApp {
}

+ (BOOL)isiOSAppOnMac {
static BOOL isiOSAppOnMac;
static BOOL isiOSAppOnMac = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (@available(iOS 14.0, *)) {
Expand All @@ -35,8 +35,18 @@ + (BOOL)isiOSAppOnMac {
return isiOSAppOnMac;
}

+ (BOOL)isiOSAppOnVision {
static BOOL isiOSAppOnVision = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSAssert(NO, @"暂不支持");
isiOSAppOnVision = NO;
});
return isiOSAppOnVision;
}

+ (BOOL)isIPad {
static BOOL isIPad;
static BOOL isIPad = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
isIPad = UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad;
Expand All @@ -45,7 +55,7 @@ + (BOOL)isIPad {
}

+ (BOOL)isIPod {
static BOOL isIPod;
static BOOL isIPod = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
isIPod = [UIDevice.currentDevice.model rangeOfString:@"iPod touch"].location != NSNotFound;
Expand All @@ -54,7 +64,7 @@ + (BOOL)isIPod {
}

+ (BOOL)isIPhone {
static BOOL isIPhone;
static BOOL isIPhone = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
isIPhone = [UIDevice.currentDevice.model rangeOfString:@"iPhone"].location != NSNotFound;
Expand All @@ -63,7 +73,7 @@ + (BOOL)isIPhone {
}

+ (BOOL)isSimulator {
static BOOL isSimulator;
static BOOL isSimulator = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#if TARGET_OS_SIMULATOR
Expand Down
18 changes: 18 additions & 0 deletions Sources/Main/JSCoreHelper+LayoutGuide.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// JSCoreHelper+LayoutGuide.h
// JSCoreKit
//
// Created by jiasong on 2024/10/16.
//

#import "JSCoreHelper.h"

NS_ASSUME_NONNULL_BEGIN

@interface JSCoreHelper (LayoutGuide)

@property (class, nonatomic, readonly) CGFloat displayScale;

@end

NS_ASSUME_NONNULL_END
22 changes: 22 additions & 0 deletions Sources/Main/JSCoreHelper+LayoutGuide.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// JSCoreHelper+LayoutGuide.m
// JSCoreKit
//
// Created by jiasong on 2024/10/16.
//

#import "JSCoreHelper+LayoutGuide.h"

@implementation JSCoreHelper (LayoutGuide)

+ (CGFloat)displayScale {
if (@available(iOS 13.0, *)) {
NSAssert(UITraitCollection.currentTraitCollection.displayScale >= 1, @"");
CGFloat displayScale = UITraitCollection.currentTraitCollection.displayScale ? : UIScreen.mainScreen.scale;
return MAX(displayScale, 1);
} else {
return MAX(UIScreen.mainScreen.scale, 1);
}
}

@end
19 changes: 19 additions & 0 deletions Sources/Main/JSCoreMacroMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,32 @@
#ifndef JSCoreMacroMethod_h
#define JSCoreMacroMethod_h

#import "JSCoreHelper+LayoutGuide.h"
#import "JSCoreMacroVariable.h"
#import <objc/runtime.h>

NS_ASSUME_NONNULL_BEGIN

#pragma mark - CGFloat

CG_INLINE CGFloat
JSCeilPixelValue(CGFloat value) {
CGFloat scale = JSCoreHelper.displayScale;
return ceil(value * scale) / scale;
}

CG_INLINE CGFloat
JSRoundPixelValue(CGFloat value) {
CGFloat scale = JSCoreHelper.displayScale;
return round(value * scale) / scale;
}

CG_INLINE CGFloat
JSFloorPixelValue(CGFloat value) {
CGFloat scale = JSCoreHelper.displayScale;
return floor(value * scale) / scale;
}

/// 检测某个数值如果为 NaN 则将其转换为 0,避免布局中出现 crash
CG_INLINE CGFloat
JSCGFloatSafeValue(CGFloat value) {
Expand Down

0 comments on commit 2a5873d

Please sign in to comment.