iOS开发-聊天emoji表情与自定义动图表情左右滑动控件

iOS开发-聊天emoji表情与自定义动图表情左右滑动控件

之前开发中遇到需要实现聊天emoji表情与自定义动图表情左右滑动控件。使用UICollectionView实现。

一、效果图

在这里插入图片描述

二、实现代码

UICollectionView是一种类似于UITableView但又比UITableView功能更强大、更灵活的视图,这是源于它将UICollectionView对cell的布局交给了UICollectionViewLayout,而且允许用户自定义layout来进行布局。

2.1 UICollectionView初始化

INEmotionView.h

@interface INEmotionView : UIView

@property (nonatomic, weak) id delegate;

@property (nonatomic, strong) INEmotionFlowLayout *flowLayout;

@property (nonatomic, strong) UICollectionView *collectionView;

@property (nonatomic, strong) UIPageControl *pageControl;

- (id)initWithFrame:(CGRect)frame;

@end

INEmotionView.m

#import "INEmotionView.h"
#import "UIColor+Addition.h"

static CGFloat kCollectionHeight = 260;

@implementation INEmotionView

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor colorWithHexString:@"efeff4"];
        
        self.flowLayout =[[INEmotionFlowLayout alloc] init];
        self.flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        
        self.collectionView = [[UICollectionView alloc]initWithFrame:frame collectionViewLayout:self.flowLayout];
        self.collectionView.backgroundColor = [UIColor clearColor];
        self.collectionView.scrollEnabled = YES;
        self.collectionView.pagingEnabled = YES;
        self.collectionView.showsVerticalScrollIndicator = NO;
        self.collectionView.showsHorizontalScrollIndicator = NO;
        self.collectionView.userInteractionEnabled = YES;
        self.collectionView.exclusiveTouch = YES;
        [self addSubview:self.collectionView];
        
        self.pageControl = [[UIPageControl alloc]initWithFrame:CGRectZero];
        self.pageControl.backgroundColor = [UIColor clearColor];
        self.pageControl.currentPage = 0;
        self.pageControl.numberOfPages = 0;
        self.pageControl.currentPageIndicatorTintColor = [UIColor redColor];
        self.pageControl.pageIndicatorTintColor = [UIColor greenColor];
        [self addSubview:self.pageControl];
    }
    return self;
}

- (id)init {
    return [self initWithFrame:CGRectZero];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.collectionView.frame = CGRectMake(0.0, (CGRectGetHeight(self.bounds) - kCollectionHeight)/2, CGRectGetWidth(self.bounds), kCollectionHeight);
    self.pageControl.frame = CGRectMake(0.0, CGRectGetMaxY(self.collectionView.frame), CGRectGetWidth(self.bounds), 50);
}

- (void)setDelegate:(id)delegate {
    _delegate = delegate;
    self.collectionView.delegate = delegate;
    self.collectionView.dataSource = delegate;
}

@end

2.2 UICollectionView实现控件

emoji表情与自定义动图表情左右切换,需要根据拆分多个section,UICollectionView的datasource
我这里使用的是5个分组,每个分组的数量如下。

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 5;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    
    NSInteger sectionNumber = 60;
    switch (section) {
        case 0:
            sectionNumber = 72;
            break;
        case 1:
            sectionNumber = 8;
            break;
        case 2:
            sectionNumber = 16;
            break;
        case 3:
            sectionNumber = 24;
            break;
        case 4:
            sectionNumber = 32;
            break;
            
        default:
            break;
    }
    return sectionNumber;
}

UICollectionView左右切换,需要将pagingEnabled设置为YES。

界面上用到了UIPageControl,由于UICollectionView继承UIScrollView。不同section的页码不一样,所以在scrollViewDidEndDecelerating方法中更改UIPageControl的numberOfPages与currentPage。

/** 手指滑动屏幕时,视图停止滚动会调用此方法 */
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    NSInteger collectionPage = scrollView.contentOffset.x/scrollView.frame.size.width;
    NSInteger aIndex = 0;
    NSInteger sectionIndex = 0;
    for (NSInteger index = 0; index < self.sectionPageNumbers.count; index ++) {
        NSString *sectionPage = [self.sectionPageNumbers objectAtIndex:index];
        aIndex = aIndex+[sectionPage integerValue];
        if (collectionPage >= 0 && collectionPage < aIndex) {
            sectionIndex = index;
            break;
        }
    }
    
    NSString *sectionCount = [self.sectionPageNumbers objectAtIndex:sectionIndex];
    NSLog(@"sectionCount:%@",sectionCount);
    
    NSInteger preCount = 0;
    for (NSInteger i = 0; i < sectionIndex; i++) {
        NSString *sectionPage = [self.sectionPageNumbers objectAtIndex:i];
        preCount = preCount + sectionPage.integerValue;
    }
    
    NSInteger sectionPageCount = sectionCount.integerValue;
    NSInteger sectionCurPage = collectionPage - preCount;
    
    NSLog(@"sectionPageCount:%ld",(long)sectionPageCount);
    NSLog(@"sectionCurPage:%ld",(long)sectionCurPage);

    self.emojiView.pageControl.numberOfPages = sectionPageCount;
    self.emojiView.pageControl.currentPage = sectionCurPage;
}

整体使用UICollectionView代理delegate方法代码如下

#import "INEmotionPresenter.h"

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

@interface INCollectionSectionPageRange : NSObject

@property (nonatomic, assign) NSString *beginNumber;
@property (nonatomic, assign) NSString *endNumber;

@end

@implementation INCollectionSectionPageRange

@end



@implementation INEmotionPresenter

#pragma mark - 注册cell
/**
 注册cell
 */
- (void)registerCollectionCell {
    [self.emojiView.collectionView registerClass:[INEmotionSystemEmojiCell class] forCellWithReuseIdentifier:kEmotionEmojiSystemIdentifier];
    [self.emojiView.collectionView registerClass:[INEmotionCustomEmojiCell class] forCellWithReuseIdentifier:kEmotionEmojiCustomIdentifier];
}

#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    UIEdgeInsets contentInset = collectionView.contentInset;
    
    NSInteger columnCount = 4;
    NSInteger rowCount = 2;
    if (indexPath.section == 0) {
        columnCount = 8;
        rowCount = 3;
    }
    CGFloat w = (CGRectGetWidth(collectionView.bounds) - contentInset.left - contentInset.right)/ columnCount;
    CGFloat h = (CGRectGetHeight(collectionView.bounds) - contentInset.top - contentInset.bottom)/rowCount;
    
    return CGSizeMake(w, h);
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 0.0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return 0.0;
}

#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 5;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    
    NSInteger sectionNumber = 60;
    switch (section) {
        case 0:
            sectionNumber = 72;
            break;
        case 1:
            sectionNumber = 8;
            break;
        case 2:
            sectionNumber = 16;
            break;
        case 3:
            sectionNumber = 24;
            break;
        case 4:
            sectionNumber = 32;
            break;
            
        default:
            break;
    }
    return sectionNumber;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        //emoji表情
        INEmotionSystemEmojiCell *cell = (INEmotionSystemEmojiCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kEmotionEmojiSystemIdentifier forIndexPath:indexPath];
        cell.emojiLabel.text = @"";
        cell.emojiLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.item];
        cell.cellNumber = [NSString stringWithFormat:@"%ld",(long)indexPath.item];
        return cell;
    }
    
    //自定义表情贴图
    INEmotionCustomEmojiCell *cell = (INEmotionCustomEmojiCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kEmotionEmojiCustomIdentifier forIndexPath:indexPath];
    cell.cellNumber = [NSString stringWithFormat:@"%ld",(long)indexPath.item];
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    NSInteger collectionPage = scrollView.contentOffset.x/scrollView.frame.size.width;
    NSInteger aIndex = 0;
    NSInteger sectionIndex = 0;
    for (NSInteger index = 0; index < self.sectionPageNumbers.count; index ++) {
        NSString *sectionPage = [self.sectionPageNumbers objectAtIndex:index];
        aIndex = aIndex+[sectionPage integerValue];
        if (collectionPage >= 0 && collectionPage < aIndex) {
            sectionIndex = index;
            break;
        }
    }
    
    NSString *sectionCount = [self.sectionPageNumbers objectAtIndex:sectionIndex];
    NSLog(@"sectionCount:%@",sectionCount);
    
    NSInteger preCount = 0;
    for (NSInteger i = 0; i < sectionIndex; i++) {
        NSString *sectionPage = [self.sectionPageNumbers objectAtIndex:i];
        preCount = preCount + sectionPage.integerValue;
    }
    
    NSInteger sectionPageCount = sectionCount.integerValue;
    NSInteger sectionCurPage = collectionPage - preCount;
    
    NSLog(@"sectionPageCount:%ld",(long)sectionPageCount);
    NSLog(@"sectionCurPage:%ld",(long)sectionCurPage);

    self.emojiView.pageControl.numberOfPages = sectionPageCount;
    self.emojiView.pageControl.currentPage = sectionCurPage;
}

#pragma mark - SETTER/GETTER
- (NSMutableArray *)sectionPageNumbers {
    if (!_sectionPageNumbers) {
        _sectionPageNumbers = [NSMutableArray arrayWithCapacity:0];
        [_sectionPageNumbers addObject:@"3"];
        [_sectionPageNumbers addObject:@"1"];
        [_sectionPageNumbers addObject:@"2"];
        [_sectionPageNumbers addObject:@"3"];
        [_sectionPageNumbers addObject:@"4"];
    }
    return _sectionPageNumbers;
}

- (INEmotionConfig *)emojiConfig {
    if (!_emojiConfig) {
        _emojiConfig = [[INEmotionConfig alloc] init];
    }
    return _emojiConfig;
}

- (INEmotionInteractor *)emojiInteractor {
    if (!_emojiInteractor) {
        _emojiInteractor = [[INEmotionInteractor alloc] init];
    }
    return _emojiInteractor;
}

- (INEmotionView *)emojiView {
    if (!_emojiView) {
        _emojiView = [[INEmotionView alloc] initWithFrame:CGRectZero];
    }
    return _emojiView;
}

@end

2.3 实现表情的排列UICollectionViewFlowLayout

由于emoji表情需要3行8列,自定义贴图表情需要2行4列排列。我这里实现一下UICollectionViewFlowLayout
要在layoutAttributesForItemAtIndexPath中区分,如果section为0,则为3行8列;否则为2行4列。

INEmotionFlowLayout.h

#import <UIKit/UIKit.h>

@interface INEmotionFlowLayout : UICollectionViewFlowLayout

- (UICollectionViewLayoutAttributes *)customLayoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

@end

INEmotionFlowLayout.m

#import "INEmotionFlowLayout.h"

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

@interface INEmotionFlowLayout () <UICollectionViewDelegateFlowLayout>

@property (strong, nonatomic) NSMutableArray *allAttributes;

@property (nonatomic, assign) NSInteger currentRow;

@property (nonatomic, assign) NSInteger currentCol;

@end

@implementation INEmotionFlowLayout

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

- (void)prepareLayout
{
    [super prepareLayout];
    
    self.allAttributes = [NSMutableArray array];
    
    NSInteger sections = [self.collectionView numberOfSections];
    for (int i = 0; i < sections; i++)
    {
        NSMutableArray * tmpArray = [NSMutableArray array];
        NSUInteger count = [self.collectionView numberOfItemsInSection:i];
        
        for (NSUInteger j = 0; j<count; j++) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:i];
            UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
            [tmpArray addObject:attributes];
        }
        
        [self.allAttributes addObject:tmpArray];
    }
}

- (CGSize)collectionViewContentSize
{
    return [super collectionViewContentSize];
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger item = indexPath.item;
    NSUInteger x;
    NSUInteger y;
    [self targetPositionWithItem:indexPath resultX:&x resultY:&y];
    NSUInteger item2 = [self originItemAtX:x y:y indexPath:indexPath];
    NSIndexPath *theNewIndexPath = [NSIndexPath indexPathForItem:item2 inSection:indexPath.section];
    
    UICollectionViewLayoutAttributes *theNewAttr = [super layoutAttributesForItemAtIndexPath:theNewIndexPath];
    theNewAttr.indexPath = indexPath;
    return theNewAttr;
}

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
    
    NSMutableArray *tmp = [NSMutableArray array];
    
    for (UICollectionViewLayoutAttributes *attr in attributes) {
        for (NSMutableArray *attributes in self.allAttributes)
        {
            for (UICollectionViewLayoutAttributes *attr2 in attributes) {
                if (attr.indexPath.item == attr2.indexPath.item) {
                    [tmp addObject:attr2];
                    break;
                }
            }
            
        }
    }
    return tmp;
}


- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    return YES;
}

// 根据 item 计算目标item的位置
// x 横向偏移  y 竖向偏移
- (void)targetPositionWithItem:(NSIndexPath *)indexPath
                       resultX:(NSUInteger *)x
                       resultY:(NSUInteger *)y
{
    NSInteger columnCount = 4;
    NSInteger rowCount = 2;
    if (indexPath.section == 0) {
        columnCount = 8;
        rowCount = 3;
    }
    
    NSInteger item = indexPath.item;
    
    NSUInteger page = item/(columnCount*rowCount);
    
    NSUInteger theX = item % columnCount + page * columnCount;
    NSUInteger theY = item / columnCount - page * rowCount;
    if (x != NULL) {
        *x = theX;
    }
    if (y != NULL) {
        *y = theY;
    }
    
}

// 根据偏移量计算item
- (NSUInteger)originItemAtX:(NSUInteger)x
                          y:(NSUInteger)y
                  indexPath:(NSIndexPath *)indexPath
{
    NSInteger columnCount = 4;
    NSInteger rowCount = 2;
    if (indexPath.section == 0) {
        columnCount = 8;
        rowCount = 3;
    }
    
    NSUInteger item = x * rowCount + y;
    return item;
}

- (UICollectionViewLayoutAttributes *)customLayoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [self layoutAttributesForItemAtIndexPath:indexPath];
}

@end

2.4 emoji表情的UICollectionViewCell

继承UICollectionViewCell实现INEmotionSystemEmojiCell表情

INEmotionSystemEmojiCell.h

#import <UIKit/UIKit.h>
#import "UIColor+Addition.h"

@interface INEmotionSystemEmojiCell : UICollectionViewCell

@property (nonatomic, strong) UIImageView *emojiImageView;

@property (nonatomic, strong) UILabel *emojiLabel;

/**
 cell的序号
 */
@property (nonatomic, strong) NSString *cellNumber;

/**
 按照序号,从小到大

 @param cell cell
 @return 排序
 */
- (NSComparisonResult)sortAscCells:(INEmotionSystemEmojiCell *)cell;

@end

INEmotionSystemEmojiCell.m

#import "INEmotionSystemEmojiCell.h"

static CGFloat kEmotionEmojiSize = 40.0;

@implementation INEmotionSystemEmojiCell

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.emojiImageView = [[UIImageView alloc] initWithFrame:CGRectMake((CGRectGetWidth(self.bounds) - kEmotionEmojiSize)/2, (CGRectGetHeight(self.bounds) - kEmotionEmojiSize)/2, kEmotionEmojiSize, kEmotionEmojiSize)];
        self.emojiImageView.backgroundColor = [UIColor randomColor];
        self.emojiImageView.layer.cornerRadius = kEmotionEmojiSize/2;
        self.emojiImageView.layer.masksToBounds = YES;
        [self addSubview:self.emojiImageView];
        
        self.emojiLabel = [[UILabel alloc] initWithFrame:CGRectMake((CGRectGetWidth(self.bounds) - kEmotionEmojiSize)/2, (CGRectGetHeight(self.bounds) - kEmotionEmojiSize)/2, kEmotionEmojiSize, kEmotionEmojiSize)];
        self.emojiLabel.textColor = [UIColor grayColor];
        self.emojiLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:self.emojiLabel];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.emojiImageView.frame = CGRectMake((CGRectGetWidth(self.bounds) - kEmotionEmojiSize)/2, (CGRectGetHeight(self.bounds) - kEmotionEmojiSize)/2, kEmotionEmojiSize, kEmotionEmojiSize);
    self.emojiLabel.frame = CGRectMake((CGRectGetWidth(self.bounds) - kEmotionEmojiSize)/2, (CGRectGetHeight(self.bounds) - kEmotionEmojiSize)/2, kEmotionEmojiSize, kEmotionEmojiSize);
}

/**
 按照序号,从小到大
 
 @param cell cell
 @return 排序
 */
- (NSComparisonResult)sortAscCells:(INEmotionSystemEmojiCell *)cell {
    //先按照时间排序
    NSComparisonResult result = [self.cellNumber compare:cell.cellNumber];
    return  result;
}

@end

2.5 自定义贴图表情的UICollectionViewCell

INEmotionCustomEmojiCell.h

#import <UIKit/UIKit.h>
#import "UIColor+Addition.h"

@interface INEmotionCustomEmojiCell : UICollectionViewCell

@property (nonatomic, strong) UIImageView *emojiImageView;

/**
 cell的序号
 */
@property (nonatomic, strong) NSString *cellNumber;

/**
 按照序号,从小到大
 
 @param cell cell
 @return 排序
 */
- (NSComparisonResult)sortAscCells:(INEmotionCustomEmojiCell *)cell;

@end

INEmotionCustomEmojiCell.m

#import "INEmotionCustomEmojiCell.h"

static CGFloat kCustomEmotionEmojiSize = 80.0;

@implementation INEmotionCustomEmojiCell

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.emojiImageView = [[UIImageView alloc] initWithFrame:CGRectMake((CGRectGetWidth(self.bounds) - kCustomEmotionEmojiSize)/2, (CGRectGetHeight(self.bounds) - kCustomEmotionEmojiSize)/2, kCustomEmotionEmojiSize, kCustomEmotionEmojiSize)];
        self.emojiImageView.backgroundColor = [UIColor randomColor];
        self.emojiImageView.layer.cornerRadius = 4;
        self.emojiImageView.layer.masksToBounds = YES;
        [self addSubview:self.emojiImageView];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.emojiImageView.frame = CGRectMake((CGRectGetWidth(self.bounds) - kCustomEmotionEmojiSize)/2, (CGRectGetHeight(self.bounds) - kCustomEmotionEmojiSize)/2, kCustomEmotionEmojiSize, kCustomEmotionEmojiSize);
}

/**
 按照序号,从小到大
 
 @param cell cell
 @return 排序
 */
- (NSComparisonResult)sortAscCells:(INEmotionCustomEmojiCell *)cell {
    //先按照时间排序
    NSComparisonResult result = [self.cellNumber compare:cell.cellNumber];
    return  result;
}

@end

至此整个效果的代码实现完了。

三、小结

iOS开发-聊天emoji表情与自定义动图表情左右滑动控件.使用UICollectionView实现。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Debian9离线安装docker

1. 前言 在服务器禁止外网访问的情况下&#xff0c;无法通过apt-get install安装docker&#xff0c;使得docker安装变得异常曲折 本地下载安装包&#xff0c;scp到服务器通过dpkg -i 手动安装&#xff0c;启动docker服务失败… … 各种坑&#xff0c;猛男也要落泪 &#x1f92…

招商银行秋招攻略和考试内容详解

招商银行秋招简介 招商银行是一家股份制商业银行&#xff0c;银行的服务理念已经深入人心&#xff0c;在社会竞争愈来愈烈的今天&#xff0c;招商银行的招牌无疑是个香饽饽&#xff0c;很多人也慕名而至&#xff0c;纷纷向招商银行投出了简历。那么秋招银行的秋招开始时间是多…

VMware虚拟机安装VMware tools

一、挂载光驱 执行以下命令来创建 /mnt/cdrom 目录&#xff1a; mkdir -p /mnt/cdrom-p 参数会确保如果 /mnt/cdrom 的上级目录&#xff08;例如 /mnt&#xff09;不存在的话也会被创建。 然后&#xff0c;你可以再次尝试挂载光盘&#xff1a; mount /dev/sr0 /mnt/cdrom这次…

面试手写实现Promise.all

目录 前言常见面试手写系列Promise.resolve 简要回顾源码实现Promise.reject 简要回顾源码实现Promise.all 简要回顾源码实现Promise.allSettled 简要回顾源码实现Promise.race 简单回顾源码实现结尾 前言 (?﹏?)曾经真实发生在一个朋友身上的真实事件&#xff0c;面试官让…

flink采用thrift读取tablets一个天坑

原先的配置 [INFO] StarRocksSourceBeReader [open Scan params.mem_limit 8589934592 B] [INFO] StarRocksSourceBeReader [open Scan params.query-timeout-s 600 s] [INFO] StarRocksSourceBeReader [open Scan params.keep-alive-min 100 min] [INFO] StarRocksSourceBeRea…

软件外包开发测试管理工具

测试是软件工程中非常重要的一个环节&#xff0c;在上线前必须需要经过严格的测试才能确保上线后软件系统长时间运行。有大量的软件开发和测试管理工具&#xff0c;每一个工具都有自己的特点&#xff0c;今天和大家分享一些常见的工具&#xff0c;希望对大家有所帮助。北京木奇…

MySQL中锁的简介——行级锁之 间隙锁 和 临键锁

1.间隙锁演示 2.临键锁演示 间隙锁锁住的是间隙&#xff0c;不包含对应的数据记录&#xff0c;而临键锁既会包含当前这条数据记录&#xff0c;也会锁定该数据记录之前的间隙。间隙锁的目的是防止其他事务插入间隙造成幻读现象。间隙锁是可以共存的&#xff0c;一个事务采用的间…

Redhat7/CentOS7 网络配置与管理(nmtui、nmcli、GNOME GUI、ifcfg文件、IP命令)

背景&#xff1a;作为系统管理员&#xff0c;需要经常处理主机网络问题&#xff0c;而配置与管理网络的方法和工具也有好几种&#xff0c;这里整理分享一下网络配置与管理的几种方式。 1、NetworkManager 概述 在 Red Hat Enterprise Linux 7 中&#xff0c;默认网络服务由 N…

python爬虫-加速乐cookie混淆解析实例小记

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站逆向实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; 第一步&#xff1a;抓包工具第一次请求页面&#xff0c;得到响应。本次我使用的fiddle进行抓包&#…

通讯录--集合动态的文件版

简易的通讯录往往需要朴实的“烹饪”就能完成一道“美味的佳肴”。 我们需要一个通讯录&#xff0c;能够存储联系人的信息&#xff0c;能够对联系人的信息进行增删查改&#xff0c;查询&#xff0c;按姓名排序。相比对之前的三子棋、扫雷&#xff0c;有了一定的了解&#xff0c…

flutter:BottomNavigationBar和TabBar

区别 BottomNavigationBarr和TabBar都是用于创建导航栏的组件&#xff0c;但它们有一些区别。 位置不同&#xff1a;BottomNavigationBar通常位于屏幕底部&#xff0c;用于主要导航&#xff1b;而TabBar通常位于屏幕顶部或底部&#xff0c;用于切换不同的视图或页面。 样式不…

[Ubuntu 22.04] containerd配置HTTP方式拉取私仓Harbor

文章目录 1. 基础环境配置2. Docker安装3. 部署Harbor&#xff0c;HTTP访问4. 部署ContainerD5. 修改docker配置文件&#xff0c;向harbor中推入镜像6. 配置containerd6.1. 拉取镜像验证6.2. 推送镜像验证 1. 基础环境配置 [Ubuntu 22.04] 安装K8S基础环境准备脚本 2. Docker安…

2023秋招面试题持续更新中。。。

目录 1.八股文渐进式MVVM三次握手&#xff0c;四次挥手viteajax组件化和模块化虚拟dom原理流程浏览器内核浏览器渲染过程回流和重绘nextTick 2.项目相关1.声明式导航和编程式导航重写push和replace方法&#xff1a;性能优化图片懒加载路由懒加载 http请求方式 1.八股文 渐进式…

shell中按照特定字符分割字符串,并且在切分后的每段内容后加上特定字符(串),然后再用特定字符拼接起来

文件中的内容&#xff0c;可以这么写&#xff1a; awk -F, -v OFS, {for(i1;i<‌NF;i){$i$i"_suffix"}}1 input.txt-F,&#xff1a;设置输入字段分隔符为逗号&#xff08;,&#xff09;&#xff0c;这将使awk按照逗号分割输入文本。-v OFS‘,’&#xff1a;设置输…

MyBatis源码分析_ResultSetHandler(7)

目录 1. 传统JDBC 2. Mybatis访问数据库 2.1 Statement访问数据库 2.2 火枪手 ResultSetHandler 出现 3. ResultSetHandler处理结果集 3.1 首先就是进入 handleResultSets 方法 3.2 handleResultSet 方法根据映射规则&#xff08;resultMap&#xff09;对结果集进行转化…

开源大模型LLaMA 2会扮演类似Android的角色么?

在AI大模型没有商业模式&#xff1f;等文章中&#xff0c;我多次表达过这样一个观点&#xff1a;不要把大模型的未来应用方式比喻成公有云&#xff0c;大模型最终会是云端操作系统的核心&#xff08;新通用计算平台&#xff09;&#xff0c;而它的落地形式会很像过去的沃森&…

linux 指令最后一期

bc ---- linux下的计算器 bc 是一个计算器 我们输入&#xff1a;quit 来退出这个计算器 我们可以这样来用&#xff1a; uname -r uname –r指令&#xff1a; 语法&#xff1a;uname [选项] 功能&#xff1a; uname用来获取电脑和操作系统的相关信息。 补充说明&#xff1a…

数据库应用:Redis安装部署

目录 一、理论 1.缓存 2.关系型数据库与非关系型数据库 3.Redis 4.Redis安装部署 5.Redis命令工具 6.Redis数据库常用命令 7.Redis多数据库操作 二、实验 1.Redis安装部署 2.Redis命令工具 3.Redis数据库命令 4.Redis多数据库操作 三、问题 1.RESP连接CentOS 7 R…

2.playbook剧本

文章目录 playbook剧本创建剧本运行剧本定义和引用变量指定远程主机sudo切换用户when条件判断剧本格式迭代with_itemswith_listwith_flattenedwith_togetherwith_cartesianwith_nested Templates模块tags模块 playbook剧本 playbooks 本身由以下各部分组成 Tasks&#xff1a;任…

操作系统启动相关概念(BIOS、MBR、GPT、BRUB)

不管是 Windows 还是 Linux 操作系统&#xff0c;底层设备一般均为物理硬件&#xff0c;操作系统启动之前会对硬件进行检测&#xff0c;然后硬盘引导启动操作系统&#xff0c;如下为操作系统启动相关的各个概念。 一、BIOS 基本输入输出系统&#xff08;Basic Input Output Sy…