如何修改第三方库

简介: 如何修改第三方库

修改第三方库最简单的是拖入工程直接修改。当然由于库间引用,导致拖入工程修改需要处理很多编译问题。指定版本后修改本地库,若别人使用时下载的库和自己的不一样。那如何不拖入工程,并且别人也能使用我们修改后的库呢?需要指定版本然后用分类。以带SceneDelegate的工程SVProgressHUD弹出框显示在左上角为例子进行解说。

一般的分类是指重载方法,不定义属性。其实分类也可以定义并使用属性。只是要想分类定义属性要自己实现setter方法和getter方法。

//给刷新控件设置 setter  getter 方法

static char * HudView = "HudView";

设置getter方法:

- (UIVisualEffectView *)hudView {

    //如果属性值是非id类型,可以通过属性值先构造OC的id对象,再通过对象获取非id类型属性
    return objc_getAssociatedObject(self, HudView);

}
//运行时实现setter方法

- (void)setHudView:(UIVisualEffectView*)hudView{

    objc_setAssociatedObject(self, HudView, hudView, OBJC_ASSOCIATION_RETAIN);

}

具体完整例子如下:

指定SVProgressHUD版本号:pod 'SVProgressHUD', '2.2.5'

SVProgressHUD+DYExtension.h文件:

#import <UIKit/UIKit.h>
#import "SVProgressHUD.h"

@interface SVProgressHUD (DYExtension)

@property (nonatomic, strong) UIVisualEffectView *hudView;
- (void)positionHUD:(NSNotification*)notification;
@end

SVProgressHUD+DYExtension.m文件:

#import "SVProgressHUD+DYExtension.h"
#import "SVIndefiniteAnimatedView.h"
#import "SVProgressAnimatedView.h"
#import "SVRadialGradientLayer.h"
#import<objc/runtime.h>

//给刷新控件设置 setter  getter 方法

static char * HudView = "HudView";

static const CGFloat SVProgressHUDParallaxDepthPoints = 10.0f;
static const CGFloat SVProgressHUDUndefinedProgress = -1;
static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15f;
static const CGFloat SVProgressHUDVerticalSpacing = 12.0f;
static const CGFloat SVProgressHUDHorizontalSpacing = 12.0f;
static const CGFloat SVProgressHUDLabelSpacing = 8.0f;

@implementation SVProgressHUD (DYExtension)

- (UIVisualEffectView *)hudView {

    //如果属性值是非id类型,可以通过属性值先构造OC的id对象,再通过对象获取非id类型属性
    return objc_getAssociatedObject(self, HudView);

}

//运行时实现setter方法

- (void)setHudView:(UIVisualEffectView*)hudView{

    objc_setAssociatedObject(self, HudView, hudView, OBJC_ASSOCIATION_RETAIN);

}


- (void)positionHUD:(NSNotification*)notification {
    CGFloat keyboardHeight = 0.0f;
    double animationDuration = 0.0;

#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS
    self.frame = [UIApplication sharedApplication].keyWindow.bounds;
    UIInterfaceOrientation orientation = UIApplication.sharedApplication.statusBarOrientation;
#elif !defined(SV_APP_EXTENSIONS) && !TARGET_OS_IOS
    self.frame= [UIApplication sharedApplication].keyWindow.bounds;
#else
    if (self.viewForExtension) {
        self.frame = self.viewForExtension.frame;
    } else {
        self.frame = UIScreen.mainScreen.bounds;
    }
#if TARGET_OS_IOS
    UIInterfaceOrientation orientation = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? UIInterfaceOrientationLandscapeLeft : UIInterfaceOrientationPortrait;
#endif
#endif
    
#if TARGET_OS_IOS
    // Get keyboardHeight in regard to current state
    if(notification) {
        NSDictionary* keyboardInfo = [notification userInfo];
        CGRect keyboardFrame = [keyboardInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
        animationDuration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        
        if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) {
            keyboardHeight = CGRectGetWidth(keyboardFrame);
            
            if(UIInterfaceOrientationIsPortrait(orientation)) {
                keyboardHeight = CGRectGetHeight(keyboardFrame);
            }
        }
    } else {
        keyboardHeight = self.visibleKeyboardHeight;
    }
#endif
    
    // Get the currently active frame of the display (depends on orientation)
    CGRect orientationFrame = self.bounds;

#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS
    CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame;
#else
    CGRect statusBarFrame = CGRectZero;
#endif
    
#if TARGET_OS_IOS
    // Update the motion effects in regard to orientation
    [self updateMotionEffectForOrientation:orientation];
#else
    [self updateMotionEffectForXMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis yMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
#endif
    
    // Calculate available height for display
    CGFloat activeHeight = CGRectGetHeight(orientationFrame);
    if(keyboardHeight > 0) {
        activeHeight += CGRectGetHeight(statusBarFrame) * 2;
    }
    activeHeight -= keyboardHeight;
    
    CGFloat posX = CGRectGetMidX(orientationFrame);
    CGFloat posY = floorf(activeHeight*0.45f);

    CGFloat rotateAngle = 0.0;
    CGPoint newCenter = CGPointMake(posX, posY);
    
    if(notification) {
        // Animate update if notification was present
        [UIView animateWithDuration:animationDuration
                              delay:0
                            options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState)
                         animations:^{
                             [self moveToPoint:newCenter rotateAngle:rotateAngle];
                             [[self getHudView] setNeedsDisplay];
                         } completion:nil];
    } else {
        [self moveToPoint:newCenter rotateAngle:rotateAngle];
    }
}
- (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle {
    [self getHudView].transform = CGAffineTransformMakeRotation(angle);
    if (self.containerView) {
        [self getHudView].center = CGPointMake(self.containerView.center.x + self.offsetFromCenter.horizontal, self.containerView.center.y + self.offsetFromCenter.vertical);
    } else {
        [self getHudView].center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical);
    }
}

#if TARGET_OS_IOS
- (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation {
    UIInterpolatingMotionEffectType xMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis : UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis;
    UIInterpolatingMotionEffectType yMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis : UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis;
    [self updateMotionEffectForXMotionEffectType:xMotionEffectType yMotionEffectType:yMotionEffectType];
}
#endif
- (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType {
    UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:xMotionEffectType];
    effectX.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints);
    effectX.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints);
    
    UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:yMotionEffectType];
    effectY.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints);
    effectY.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints);
    
    UIMotionEffectGroup *effectGroup = [UIMotionEffectGroup new];
    effectGroup.motionEffects = @[effectX, effectY];
    
    // Clear old motion effect, then add new motion effects
    [self getHudView].motionEffects = @[];
    [[self getHudView] addMotionEffect:effectGroup];
}
- (UIVisualEffectView*)getHudView {
    if(!self.hudView) {
        self.hudView = [UIVisualEffectView new];
        self.hudView.layer.masksToBounds = YES;
        self.hudView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
    }
    if(!self.hudView.superview) {
        [self addSubview:self.hudView];
    }

    // Update styling
    self.hudView.layer.cornerRadius = self.cornerRadius;

    return self.hudView;
}


- (CGFloat)visibleKeyboardHeight {
#if !defined(SV_APP_EXTENSIONS)
    UIWindow *keyboardWindow = nil;
    for (UIWindow *testWindow in UIApplication.sharedApplication.windows) {
        if(![testWindow.class isEqual:UIWindow.class]) {
            keyboardWindow = testWindow;
            break;
        }
    }
    
    for (__strong UIView *possibleKeyboard in keyboardWindow.subviews) {
        NSString *viewName = NSStringFromClass(possibleKeyboard.class);
        if([viewName hasPrefix:@"UI"]){
            if([viewName hasSuffix:@"PeripheralHostView"] || [viewName hasSuffix:@"Keyboard"]){
                return CGRectGetHeight(possibleKeyboard.bounds);
            } else if ([viewName hasSuffix:@"InputSetContainerView"]){
                for (__strong UIView *possibleKeyboardSubview in possibleKeyboard.subviews) {
                    viewName = NSStringFromClass(possibleKeyboardSubview.class);
                    if([viewName hasPrefix:@"UI"] && [viewName hasSuffix:@"InputSetHostView"]) {
                        CGRect convertedRect = [possibleKeyboard convertRect:possibleKeyboardSubview.frame toView:self];
                        CGRect intersectedRect = CGRectIntersection(convertedRect, self.bounds);
                        if (!CGRectIsNull(intersectedRect)) {
                            return CGRectGetHeight(intersectedRect);
                        }
                    }
                }
            }
        }
    }
#endif
    return 0;
}
@end
目录
相关文章
|
机器学习/深度学习 存储 缓存
数据结构从入门到精通——算法的时间复杂度和空间复杂度
算法的时间复杂度和空间复杂度是评估算法性能的两个重要指标。时间复杂度主要关注算法执行过程中所需的时间随输入规模的变化情况,而空间复杂度则关注算法执行过程中所需的最大存储空间或内存空间。
758 0
|
Swift iOS开发 Ruby
iOS CocoaPods 使用以及常见问题(上)
iOS CocoaPods 使用以及常见问题
659 0
系列文章深度解读|SwiftUI 背后那些事儿
前言 今年苹果的WWDC你看了吗?苹果在2019年的WWDC的重头戏当然非SwiftUI莫属:全新的声明式语法、绑定式API、和响应式变成框架Combine。这一切的一切都预示着即将在Apple Native布局系统掀起一场革命。
18029 0
|
5月前
|
人工智能 Nacos 开发者
Nacos 开源 MCP Router,加速 MCP 私有化部署
Nacos MCP Router 发布全新版本。带来了多项重要更新,包括对 SSE 和 StreamableHTTP 协议的全面支持、Docker 容器化部署方案以及革命性的 MCP Server 协议一键转换功能。文章中详细的介绍更新内容并简单演示了使用过程。Nacos MCP Router 新版本的发布,不仅提升了开发者的使用体验,也为 MCP 服务的广泛应用和生态繁荣奠定了基础,欢迎关注。
1449 63
|
6月前
|
存储 人工智能 关系型数据库
向量数据库和嵌入模型
本文介绍了向量数据库和嵌入模型的概念及应用,重点探讨了两者在AI技术栈中的协作关系。向量数据库是一种用于存储高维向量数据的解决方案,支持相似性搜索而非传统的关系型数据库精确匹配。文中通过实例展示了如何使用阿里百炼的文本嵌入模型(text-embedding-v3)将文本向量化,并结合Qdrant向量数据库进行存储与检索。代码示例部分详细说明了从文本嵌入到向量存储及查询的完整流程,为开发者提供了实践参考。
860 15
向量数据库和嵌入模型
|
11月前
|
人工智能 Java 程序员
HarmonyOS实战开发之HMRouter实现跳转
本文介绍了HarmonyOS页面跳转的两种方式:组件导航(Navigation)和页面路由(@ohos.router),并推荐使用更灵活的组件导航。进一步详细讲解了HMRouter,一个解决HarmonyOS页面跳转问题的框架,其功能包括页面跳转、弹窗提示、转场动效等。通过下载依赖、配置插件、初始化和实现跳转四个步骤,可以轻松集成HMRouter,实现高效页面管理。文章还展示了具体代码示例和效果截图,帮助开发者快速上手。关注Feri,带你掌握鸿蒙开发技巧!
730 1
|
9月前
|
人工智能 Java 程序员
一文彻底拿下HarmonyOS实战开发之HMRouter实现跳转
本文介绍HarmonyOS页面跳转的两种方式:组件导航(Navigation)和页面路由(@ohos.router)。重点推荐使用组件导航,因其灵活性和多端部署能力更强。此外,还介绍了HMRouter,一个简化页面跳转的工具,支持自定义注解、路由拦截、动画配置等功能。通过详细步骤,展示了如何在项目中集成HMRouter并实现页面跳转,帮助开发者更高效地开发鸿蒙应用。君志所向,一往无前!关注我,带你起飞鸿蒙开发!
842 0
|
负载均衡 安全 Cloud Native
Web应用防火墙
本文介绍了Web应用防火墙(Web Application Firewall,简称WAF)2.0和3.0版本的关系、区别、如何快速使用WAF。
392 1
|
安全 iOS开发
iOS页面布局:UIScrollView的布局问题
iOS页面布局:UIScrollView的布局问题
545 63
|
Swift iOS开发
iOS 用一个布局来解决嵌套问题—— UICollectionViewCompositionalLayout
iOS 用一个布局来解决嵌套问题—— UICollectionViewCompositionalLayout
iOS 用一个布局来解决嵌套问题—— UICollectionViewCompositionalLayout