iOS开发-转场动画切换界面(类似系统动画)

news2024/11/16 12:50:17

iOS开发-转场动画切换界面(类似系统动画)

在开发中,无论我们使用 push 还是 present 推出新的 viewcontroller 时,系统为了提高用户体验都会为我们默认加上一些过渡动画。但是开发中需要自定义过度动画效果。这里就需要用到了转场动画了。

如图所示

在这里插入图片描述

在这里插入图片描述

一、转场动画相关协议

自定义转场动画时需要使用的协议:

  • UIViewControllerAnimatedTransitioning: 实现此协议的实例控制转场动画效果。
  • UIViewControllerInteractiveTransitioning: 实现此协议的实例控制着利用手势过渡时的进度处理。

二、实现转场动画代码

2.1、实现UIViewControllerAnimatedTransitioning协议

实现转场动画时候,实现UIViewControllerAnimatedTransitioning协议

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext;

在区分Push与Pop操作时候,需要用到以下的

UIView *containerView = [transitionContext containerView];

    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIView *fromView = fromVC.view;
    
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toVC.view;

注意:在转场过程中,转场过渡的容器,如果是PUSH时候,A->B是,fromVC是A,toVC是B;如果是POP的时候,fromVC是B,toVC是A。

动画实现
在转场过程中更改fromView与toView的toFrame,动画结束后调用transitionContext的completeTransition方法。

具体代码如下

INPushPopTranstioning.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "INPercentDrivenInteractiveTransition.h"

@interface INPushPopTranstioning : NSObject<UIViewControllerAnimatedTransitioning, UINavigationControllerDelegate>

// 是否是Push
@property (nonatomic, assign) NSTimeInterval transitionDuration;

@property (nonatomic, strong) INPercentDrivenInteractiveTransition *interactiveTransition;

+ (instancetype)sharedInstance;

@end

INPushPopTranstioning.m

#import "INPushPopTranstioning.h"

#define kINScreenWidth [[UIScreen mainScreen] bounds].size.width

static INPushPopTranstioning *_sharedInstance = nil;

@interface INPushPopTranstioning ()

// 是否是Push
@property (nonatomic, assign) BOOL isPush;

@end

@implementation INPushPopTranstioning

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[INPushPopTranstioning alloc] init];
        _sharedInstance.transitionDuration = 0.35;
        _sharedInstance.interactiveTransition = [[INPercentDrivenInteractiveTransition alloc] init];
    });
    
    return _sharedInstance;
}

- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                                   interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController {
    return self.interactiveTransition.isInteractive?self.interactiveTransition:nil;
}

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
    return self.transitionDuration;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    
    // 转场过渡的容器 如果是PUSH时候,A->B是,fromVC是A,toVC是B;如果是POP的时候,fromVC是B,toVC是A。
    // Transition container
    UIView *containerView = [transitionContext containerView];

    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIView *fromView = fromVC.view;
    
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toVC.view;

    UIImage *fromImage = [self screenShotImage:fromView];
    
    UIImageView *backView = [[UIImageView alloc] initWithFrame:CGRectZero];
    //backView.image = fromImage;
    backView.backgroundColor = [UIColor blackColor];
    backView.frame = containerView.bounds;
    
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    effectView.frame = backView.bounds;
    //[backView addSubview:effectView];

    UIImageView *viewMaskView = [[UIImageView alloc] initWithFrame:CGRectZero];
    viewMaskView.backgroundColor = [UIColor blackColor];
    viewMaskView.frame = containerView.bounds;
    
    // 判断是 push 还是 pop 操作
    // Determine if it is a push or pop operation
    if (self.isPush) {
        //[containerView addSubview:backView];
        [containerView addSubview:fromView];
        [containerView addSubview:viewMaskView];
        [containerView addSubview:toView];

    } else {
        //[containerView addSubview:backView];
        [containerView addSubview:toView];
        [containerView addSubview:viewMaskView];
        [containerView addSubview:fromView];
    }
    
    
    CGRect fromFrame;
    CGRect toFrame;

    CGFloat beginAlpha = 0.0;
    if (self.isPush) {
        fromFrame = containerView.bounds;
        fromView.frame = fromFrame;
        
        toFrame = CGRectMake(containerView.bounds.size.width, 0, containerView.bounds.size.width, containerView.bounds.size.height);
        toView.frame = toFrame;        
        beginAlpha = 0.0;
    } else {
        fromFrame = containerView.bounds;
        fromView.frame = fromFrame;
        
        toFrame = CGRectMake(containerView.bounds.size.width, 0, containerView.bounds.size.width, containerView.bounds.size.height);
        
        toView.frame = fromFrame;
        
        beginAlpha = 0.3;
    }

    viewMaskView.alpha = beginAlpha;
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        if (self.isPush) {
            //fromView.transform = CGAffineTransformMakeScale(0.9, 0.9);
            toView.frame = fromFrame;
            viewMaskView.alpha = 0.3;
        } else {
            fromView.frame = toFrame;
            //toView.transform = CGAffineTransformMakeScale(1.0, 1.0);
            viewMaskView.alpha = 0.0;
        }
    } completion:^(BOOL finished) {
        BOOL cancelled = [transitionContext transitionWasCancelled];
        
        fromView.transform = CGAffineTransformIdentity;
        toView.transform = CGAffineTransformIdentity;

        // 删除遮罩
        [backView removeFromSuperview];
        [viewMaskView removeFromSuperview];
        
        // 设置 transitionContext 通知系统动画执行完毕
        [transitionContext completeTransition:!cancelled];
    }];
}

- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC {
    if (operation == UINavigationControllerOperationPush) {
        self.isPush = YES;
    } else {
        self.isPush = NO;
    }
    return self;
}

- (UIImage *)screenShotImage:(UIView *)view {
    // 第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传NO,否则传YES。第三个参数就是屏幕密度了,设置为[UIScreen mainScreen].scale可以保证转成的图片不失真。
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO,[UIScreen mainScreen].scale);
    if ([view respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
        [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
    } else {
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    }
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return viewImage;
}

// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    NSLog(@"willShowViewController:%@",viewController);
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    NSLog(@"didShowViewController:%@",viewController);
}

- (CATransform3D)transformRotation:(CGFloat)angle {
    CATransform3D rotation3DIdentity = CATransform3DIdentity;
    rotation3DIdentity.m34 = 0.3/500.0;
    CATransform3D rotateTransform = CATransform3DRotate(rotation3DIdentity, angle, 0, 1, 0);
    CATransform3D transform = CATransform3DMakeTranslation(0, 0, kINScreenWidth/4.0);
    return CATransform3DConcat(rotateTransform, transform);
}

- (void)resetAnChorPoint:(UIView *)view anchorPoint:(CGPoint)anchorPoint {
    CGPoint oldAnchorPoint = view.layer.anchorPoint;
    view.layer.anchorPoint = anchorPoint;
    [view.layer setPosition:CGPointMake(view.layer.position.x + view.layer.bounds.size.width * (view.layer.anchorPoint.x - oldAnchorPoint.x), view.layer.position.y + view.layer.bounds.size.height * (view.layer.anchorPoint.y - oldAnchorPoint.y))];
}

@end

2.2、处理手势过渡

在Pop可能需要手势滑动返回,我这里使用继承UIPercentDrivenInteractiveTransition的子类INPercentDrivenInteractiveTransition来处理

实现拖拽手势UIPanGestureRecognizer

代码如下

INPercentDrivenInteractiveTransition.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface INPercentDrivenInteractiveTransition : UIPercentDrivenInteractiveTransition

@property (nonatomic, assign, readonly) BOOL isInteractive;

@end

NS_ASSUME_NONNULL_END

INPercentDrivenInteractiveTransition.m

#import "INPercentDrivenInteractiveTransition.h"

// 屏幕宽与高
#define kScreenWidth  ([UIScreen mainScreen].bounds.size.width)
#define kScreenHeight ([UIScreen mainScreen].bounds.size.height)

@interface INPercentDrivenInteractiveTransition()

@property (nonatomic, assign, readwrite) BOOL isInteractive;

@end

@implementation INPercentDrivenInteractiveTransition

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.isInteractive = NO;
    }
    return self;
}

- (void)handleGesture:(UIPanGestureRecognizer *)panGesture {
    CGFloat transitionX = [panGesture translationInView:panGesture.view].x;
    CGFloat persent = transitionX / panGesture.view.frame.size.width;
    
    switch (panGesture.state) {
        case UIGestureRecognizerStateBegan:
            self.isInteractive = YES;
            [self start];
            break;
        case UIGestureRecognizerStateChanged:
            [self updateInteractiveTransition:persent];
            break;
        case UIGestureRecognizerStateEnded:
            self.isInteractive = NO;
            if (persent > 0.5) {
                [self finishInteractiveTransition];
            }else{
                [self cancelInteractiveTransition];
            }
            break;
        default:
            break;
    }
}

- (void)start {
    UIViewController *controller = [self getCurrentWindowController];
    [controller.navigationController popViewControllerAnimated:YES];
}

/**
 获取当前屏幕显示的controller

 @return controller
 */
- (UIViewController *)getCurrentWindowController {
    UIViewController *result = nil;
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    if (window.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(UIWindow * tmpWin in windows) {
            if (tmpWin.windowLevel == UIWindowLevelNormal) {
                window = tmpWin;
                break;
            }
        }
    }
    
    result = window.rootViewController;
    
    while (result.presentingViewController) {
        result = result.presentingViewController;
    }
    
    if ([result isKindOfClass:[UITabBarController class]]) {
        result = [(UITabBarController *)result selectedViewController];
    }
    
    if ([result isKindOfClass:[UINavigationController class]]) {
        result = [(UINavigationController *)result visibleViewController];
    }

    return result;
}

@end

2.3、UINavigationController扩展Category

在Push与Pop时候需要转场动画,那需要替换UINavigationController中的方法

需要使用method_exchangeImplementations

这里暂不详细说明方法替换的逻辑了,详细参考

https://blog.csdn.net/gloryFlow/article/details/131677505

具体代码如下

UINavigationController+Transition.h

#import <UIKit/UIKit.h>
#import "UIViewController+Transition.h"

/**
 处理转场动画
 */
@interface UINavigationController (Transition)


@end

UINavigationController+Transition.m

#import "UINavigationController+Transition.h"
#import <objc/runtime.h>
#import "INPushPopTranstioning.h"

@implementation UINavigationController (Transition)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        method_exchangeImplementations(class_getInstanceMethod(class, @selector(popViewControllerAnimated:)), class_getInstanceMethod(class, @selector(in_popViewControllerAnimated:)));
        method_exchangeImplementations(class_getInstanceMethod(class, @selector(pushViewController:animated:)), class_getInstanceMethod(class, @selector(in_pushViewController:animated:)));
    });
}

- (void)in_pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (animated && [INPushPopTranstioning sharedInstance].transitionDuration > 0.0) {
        // 跳转到某些ViewController,需要特定的转场动画,需要设置showNavTransitionDelegate。
        if (viewController.showNavTransitionDelegate) {
            self.delegate = viewController.showNavTransitionDelegate;
        } else {
            self.delegate = [INPushPopTranstioning sharedInstance];
        }
    }
    
    [self in_pushViewController:viewController animated:animated];
}

- (nullable UIViewController *)in_popViewControllerAnimated:(BOOL)animated {
    if (animated && [INPushPopTranstioning sharedInstance].transitionDuration > 0.0) {
        // 回到到某些ViewController,需要特定的转场动画,需要设置showNavTransitionDelegate。
        if (self.visibleViewController.showNavTransitionDelegate) {
            self.delegate = self.visibleViewController.showNavTransitionDelegate;
        } else {
            self.delegate = [INPushPopTranstioning sharedInstance];
        }
    }
    return [self in_popViewControllerAnimated:animated];
}

@end

2.4、UIViewController扩展Category

我这里扩展UIViewController添加运行时属性,代码如下

UIViewController+Transition.h

#import <UIKit/UIKit.h>

@interface UIViewController (Transition)

@property (nonatomic, weak) id <UINavigationControllerDelegate> showNavTransitionDelegate;

@end

UIViewController+Transition.m

#import "UIViewController+Transition.h"
#import <objc/runtime.h>

static const void *showTransitionKey = &showTransitionKey;

@implementation UIViewController (Transition)

- (id<UINavigationControllerDelegate>)showNavTransitionDelegate {
    return objc_getAssociatedObject(self, showTransitionKey);
}

- (void)setShowNavTransitionDelegate:(id<UINavigationControllerDelegate>)showNavTransitionDelegate {
    objc_setAssociatedObject(self, showTransitionKey, showNavTransitionDelegate, OBJC_ASSOCIATION_ASSIGN);
}

@end

2.4、UIViewController扩展Category Navigation

UIViewController+Navigation.h

#import <UIKit/UIKit.h>

@interface UIViewController (Navigation)

@property (nonatomic, weak) UINavigationController *in_navigationController;

@end

UIViewController+Navigation.m

#import "UIViewController+Navigation.h"
#import <objc/runtime.h>

static const void *showNavTransitionKey = &showNavTransitionKey;

@implementation UIViewController (Navigation)

- (UINavigationController *)in_navigationController {
    return objc_getAssociatedObject(self, showNavTransitionKey);
}

- (void)setIn_navigationController:(UINavigationController *)in_navigationController {
    objc_setAssociatedObject(self, showNavTransitionKey, in_navigationController, OBJC_ASSOCIATION_ASSIGN);
}

@end

三、使用自定义转场动画

在BaseViewController中添加拖拽手势,用于处理手势滑动返回。

UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:[INPushPopTranstioning sharedInstance].interactiveTransition action:@selector(handleGesture:)];
    pan.edges = UIRectEdgeLeft;
    [self.view addGestureRecognizer:pan];

BaseViewController完整代码如下

INBaseViewController.h

#import <UIKit/UIKit.h>
#import "UIViewController+Navigation.h"

NS_ASSUME_NONNULL_BEGIN

@interface INBaseViewController : UIViewController

@property (nonatomic, assign) BOOL isViewDidAppear;

@end

NS_ASSUME_NONNULL_END

INBaseViewController.m

#import "INBaseViewController.h"
#import "INPushPopTranstioning.h"

@interface INBaseViewController ()

@end

@implementation INBaseViewController

- (id)init {
    self = [super init];
    if (self) {
        self.hidesBottomBarWhenPushed = YES;
        [self setNeedsStatusBarAppearanceUpdate];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.exclusiveTouch = YES;
    self.view.clipsToBounds = YES;
    
    self.automaticallyAdjustsScrollViewInsets = NO;
    self.extendedLayoutIncludesOpaqueBars = YES;
    
    UIScreenEdgePanGestureRecognizer *pan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:[INPushPopTranstioning sharedInstance].interactiveTransition action:@selector(handleGesture:)];
    pan.edges = UIRectEdgeLeft;
    [self.view addGestureRecognizer:pan];
}

- (void)loadView {
    [super loadView];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.isViewDidAppear = NO;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.isViewDidAppear = NO;
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.isViewDidAppear = YES;
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    self.isViewDidAppear = NO;
}

- (void)handleGesture:(UIScreenEdgePanGestureRecognizer *)gestureRecognizer {
    // 手势
}

#pragma mark - StatusBar style
- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleDefault;
}

- (BOOL)prefersStatusBarHidden {
    return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

- (BOOL)shouldAutorotate {
    return NO;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)dealloc {
    NSLog(@"DEALLOCBaseViewController");
}

@end

我这里使用的是NavigationController嵌套自定义的TabbarController.

在AppDelegate中didFinishLaunchingWithOptions进行设置

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window makeKeyAndVisible];
    
    
    INMainTabBarController *tabbar = [[INMainTabBarController alloc] init];
    UINavigationController *mainNav = [[UINavigationController alloc] initWithRootViewController:tabbar];
    mainNav.delegate = [INPushPopTranstioning sharedInstance];
    
    self.window.backgroundColor = [UIColor whiteColor];
    self.window.rootViewController = mainNav;
    
    return YES;
}

三、小结

iOS开发-转场动画切换界面(类似系统动画)。UIViewControllerAnimatedTransitioning与UIViewControllerInteractiveTransitioning。

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/810545.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二十五章:用于弱监督语义分割的激活调节和重新校准方案

0.摘要 图像级弱监督语义分割&#xff08;WSSS&#xff09;是一项基础而具有挑战性的计算机视觉任务&#xff0c;有助于场景理解和自动驾驶。大多数现有方法利用基于分类的类激活图&#xff08;CAMs&#xff09;作为初始伪标签&#xff0c;但这些方法往往关注区分性的图像区域&…

Leetcode刷题---C语言实现初阶数据结构---单链表

1 删除链表中等于给定值 val 的所有节点 删除链表中等于给定值 val 的所有节点 给你一个链表的头节点head和一个整数val&#xff0c;请你删除链表中所有满足Node.valval的节点&#xff0c;并返回新的头节点 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[…

Tomcat 的使用(图文教学)

Tomcat 的使用&#xff08;图文教学&#xff09; 前言一、什么是Tomcat&#xff1f;二、Tomcat 服务器和 Servlet 版本的对应关系三、Tomcat 的使用1、安装2、目录介绍3、如何启动4、Tomcat 的停止5、如何修改 Tomcat 的端口号6、如何部暑 web 工程到 Tomcat 中6.1 方式一6.2 …

建设银行秋招指南,备考技巧和考试内容详解

建设银行秋招简介 银行作为非常吃香的岗位&#xff0c;每年都有不少同学通过投递简历&#xff0c;进入笔试&#xff0c;再到面试成功&#xff0c;成功到银行就职&#xff0c;也有相当一部分同学因为信息差&#xff0c;符合条件却没有报名。无法进入银行工作。 建设银行的秋招…

从保存受限的手机APP中提取文件(读取Android系统中的新增缓存文件)

这个手机APP的权限可能设置了无法在应用内保存文件&#xff0c;但是这个文件实际上一定存在于本地的某个地方&#xff0c;本文的方法通过遍历最后修改日期在今天的文件&#xff0c;很容易就可以找到它。 首先安装一个QPython&#xff0c;这个软件可以允许你在安卓手机上运行Py…

Linux常用命令——dpkg-reconfigure命令

在线Linux命令查询工具 dpkg-reconfigure Debian Linux中重新配制一个已经安装的软件包 补充说明 dpkg-reconfigure命令是Debian Linux中重新配置已经安装过的软件包&#xff0c;可以将一个或者多个已安装的软件包传递给此指令&#xff0c;它将询问软件初次安装后的配置问题…

平板光波导中导模的(注意不是泄露模)传播常数β的matlab计算(验证了是对的)

参照的是导波光学_王建(清华大学)的公式(3-1-2、3-1-3)&#xff0c;算的参数是这本书的图3-3的。 function []PropagationConstantsMain() clear;clc;close all lambda01.55;%真空或空气中的入射波长&#xff0c;单位um k02*pi/lambda0; m3;%导模阶数(需要人为指定) n11.62;%芯…

Godot 4 源码分析 - 动态导入图片文件

用Godot 4尝试编一个电子书软件&#xff0c;初步效果已经出来&#xff0c;并且通过管道通信接口可以获取、设置属性、调用函数&#xff0c;貌似能处理各种事宜了。 其实不然&#xff0c;外因通过内因起作用&#xff0c;如果没把里面搞明白&#xff0c;功能没有开放出来&#x…

Android 13(T) - Media框架(1)- 总览

从事Android Media开发工作三年有余&#xff0c;刚从萌新变成菜鸟&#xff0c;一路上跌跌撞撞学习&#xff0c;看了很多零零碎碎的知识&#xff0c;为了加深对Android Media框架的理解&#xff0c;决定在这里记录下学习过程中想到的一些问题以及一些思考&#xff0c;也希望对初…

国产颗粒更快更稳,价格厚道的光威天策弈系列DDR4内存条值得安排

想要用最少的费用打造出一台性能强悍的电脑&#xff0c;自己动手DIY组装电脑是个更好的选择&#xff0c;特别是今年硬盘和内存方面降价潮此起彼伏&#xff0c;出现了很多神价&#xff0c;高性能内存和硬盘对平台性能提升的效果也是非常显著的。 相比于传统大厂的内存&#xff0…

心法利器[92] | 谈校招:刷题和笔试准备

心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会&#xff0c;与大家一起成长。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。 2022年新一版的文章合集已经发布&#xff0c;累计已经60w字了&#xff0c;获取方式看这里&…

Linux NUMA架构(非统一内存访问)

NUMA架构 NUMA Architecture| Non Uniform Memory Access Policy/Model | Numa Node Configuration (CPU Affinity) NUMA架构产生的原因 cpu的高速处理功能和内存存储直接的速度会严重影响cpu的性能。传统的计算机单核架构,cpu通过内存总线(内存访问控制器)直接连接到一…

【Linux基础】WSL安装Ubuntu

说明 本文使用的Windows环境是Windows 11 专业版。 WSL现在有二代WSL2&#xff0c;后续都通过WSL2来安装Linux&#xff0c;使用的是Ubuntu发行版&#xff0c;版本是20.04。 安装过程使用了PowerShell&#xff0c;且是管理员权限打开的。 参考适用于 Linux 的 Windows 子系统…

【 Spring AOP学习二】统一功能处理:拦截器异常返回数据格式

目录 一、用户登录权限效验 &#x1f351;1、Spring拦截器实现用户统一登录验证&#xff08;重要&#xff09; &#xff08;1&#xff09;定义一个拦截器 &#xff08;2&#xff09;将自定义拦截器加入到系统配置中 &#x1f351;2、拦截器实现原理 &#x1f351;3、统一…

car tire

汽车轮胎规则参数 小车、轿车轮胎规格参数图解-有驾 半挂车轮胎尺寸多少 货车轮胎尺寸对照表【汽车时代网】

二叉树的最大深度和最小深度(两种方法:递归+迭代)

二叉树的最大深度&#xff1a; class Solution { public:int maxDepth(TreeNode* root) {//DFS 深度优先搜索if(rootNULL) return 0;//深度等于max&#xff08;左子树的深度&#xff0c;右子树的深度&#xff09;1&#xff1b;return max(maxDepth(root->left),maxDepth(roo…

QT自定义控件实现并导入

QT自定义控件 介绍 QT Creator自定义控件和designer控件导入 1.安装QT5.7.1 2.将QT编译器目录、lib目录、include目录导入path 使用说明 使用说明按照 1.创建QtDesigner自定义控件工程&#xff0c;打开Qt Creator,创建一个Qt 设计师自定义控件&#xff0c;如下图所示&#xf…

靠着AI自动生成视频撸自媒体收益,赚了包辣条~

友友们&#xff0c;小卷今天给大家分享下如何通过AI自动生成视频&#xff0c;只需要3分钟就能做出一个视频&#xff0c;把视频发到B站、抖音、西瓜上&#xff0c;还能赚包辣条哦~ 文末给大家准备了AI变现的案例及AIGC知识库&#xff0c;记得领取哦&#xff01; 1.收益 先看看收…

手写SpringBoot模拟核心流程

首先&#xff0c;SpringBoot是基于的Spring&#xff0c;所以我们要依赖Spring&#xff0c;然后我希望我们模拟出来的SpringBoot也支持Spring MVC的那一套功能&#xff0c;所以也要依赖Spring MVC&#xff0c;包括Tomcat等&#xff0c;所以在SpringBoot模块中要添加以下依赖&…

13. Mybatis-Plus

目录 1. MyBatis-Plus 简介 2. 新建项目 3. 添加依赖 4. 配置数据库 5. 编码 1. MyBatis-Plus 简介 通过官网&#xff1a;MyBatis-Plus MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window)的增强工具&#xff0c;在 MyB…