iOS ------ Block的总结

news2024/11/16 16:37:55

前面看了Block的基本知识,和一些源码。但对于block怎么用的还不了解,代码中出现block会看不懂,现在来具体看一下Block的用法并做个总结。

1.Block是什么

block对象是一个C语言结构体,可以并入C和OC的代码中,Block本质是一个匿名函数,以及与该函数一起使用的数据,其他语言有时称为闭包或ambda。Block特别适合于回调,或者是在你为了让代码看起来具有更清晰的逻辑进行代码的组合时使用。

上面是苹果官方的解释,告诉我们:首先Block是一个OC中的对象,并且这个对象是一个C语言的结构体,它可以使用在C语言和OC中;同时,Block本质是一个匿名函数和其包含的数据集中

2.为什么用Block

苹果官方的文档的描述

  1. 代替代理和委托方法
  2. 作为回调函数的代替
  3. 一次性编写多次处理的任务
  4. 方便对集合中的所有项执行任务
  5. 与GCD队列一起执行异步任务

以上这些情况,我们都能够使用Block。我感受最深刻的是使用Block回调,很多情况下,我们可能只需要对某个事件进行一个简单的回调,也许就仅仅一次,如果我们使用代理的话,我们需要创建类,编写协议,仅仅对一个小地方的回调成本很高,那么Block的使用就恰到好处。除此之外,Block的特性还可以让代理集中在某处,我们只需要在一个地方就可以完成回调之前和回调时的代码,相比,使用回调函数和代理都没有这个优势。另外,我门可以想到,OC中封装了一些集合分方法,比如数组的排序,这里就使用Block进行回调操作的。

简单讲一下回调的概念

将一段代码和一个特定的事件联系在一起,当特定事件发生后,这段代码才会被执行。
OC的几种回调

  • Targe-action回调
  • delegate方式
  • NOtification方式
  • block方式

OC的的回调几种方式

3.怎么使用Block

我们先创建一个Block,并简单的使用
在这里插入图片描述

运行结果
在这里插入图片描述
这里是为了强调block的回调效果。可以发现,尽管block的代码早就声明了,但是没用立即调用,而是在block的调用的时候,才被执行。到这里应该对Block的回调有一定的理解。

这好像并没有什么用处,下面看一看另外两种Block的使用。前面说block是OC的一个对象,既然是对象,我们可以把它当做一个类分属性,应该也可以更其他属性一样,被当作一个方法的参数吧。这也是block被大家认可的地方。

假设我们有这样一个类:包含一个block属性testBlock,包含一个调用自己的block属性的方法blockDo。

@interface Computer : NSObject
@property (nonatomic, copy) NSString* (^testBlock)(NSString*);//将block作为computer的属性
- (void)blockDo;
@end

#import "Computer.h"
@implementation Computer
- (void)blockDo {
    NSString* testString = @"textData_old";
    if (self.testBlock) {
        NSLog(@"%@", self.testBlock(testString));//调用并打印
    }
}
@end

在其他地方写下这些代码

Computer* computer = [[Computer alloc] init];
        computer.testBlock =  ^(NSString* parStr){
            NSLog(@"%@",parStr);
            parStr = @"testData_New";
            return parStr;
        };
        [computer blockDo]; //执行Block

运行结果
在这里插入图片描述

这里的调用就比前面的复杂了。因为我给Computer添加了一个方法,并且将block的调用交给了Computer,我只是实现了block而已,最后启动调用它的方法。我们在另一个地方对Computer类模拟了一个方法(也就是块,这个方法没有在Computer类中实现,我们甚至可以在任何地方实现它,最后我们可以在其他地方调用。这就是Block的神奇的地方。

再来看一个

@interface Computer2 : NSObject
- (void)doSomthingFeedBakck:(NSString* (^)(NSString*))handle;
@end
#import "Computer2.h"

@implementation Computer2
-(void)doSomthingFeedBakck:(NSString * _Nonnull (^)(NSString * _Nonnull))handle {
    NSString* handleStr = @"Old";
    sleep(3.0);
    NSLog(@"%@", handle(handleStr));
}
@end

其他地方调用

Computer2* computer2 = [[Computer2 alloc] init];
        [computer2 doSomthingFeedBakck:^NSString * _Nonnull(NSString * parStr) {
            NSLog(@"%@", parStr);
            NSString* returnstr = [NSString stringWithFormat:@"add %@", parStr];
            return returnstr;
        }];

运行结果
在这里插入图片描述

这里讲Block作为一个参数放在doSomthingFeedBakck函数面。体现了block的对象本质,相比之下,代码很是简洁。这种实现回调的方法逻辑更加清晰,明朗。

上面三个例子,展示了block的三种不同的使用方式。它们分别是:

  • 将block定义成员变量
  • 将block定义成属性
  • 将block作为参数

4.总结

通过上面的block的额用法发现,block每次回调是通过它的匿名函数进行的,也就是每次最多执行一个回调,在需要进行大批量的回调的时候,就需要写很多不同的block回调,这样就不合适这时使用协议和代理的方式就自然多了。除此之外,block还比较适合线程之间的切换回调,GCD就是采用了多线程结合block来做的。

5.下面我们记录一些block的原理性知识

  • 为什么说block是一个结构体,也是一个对象,同时还是携带数据的匿名函数
  • 全局block,栈block,以及堆区block的区别和他们之间的联系,探究block的内存管理
  • 为什么使用_block就可以使block可以修改外部变量
  • 引起强引用的原因是什么,我们解决的方法和原理是什么

1,为什么说block是一个结构体,也是一个对象,同时还是携带数据的匿名函数

使用Mac终端,cd将图中的第一个文件拖入

在这里插入图片描述

文件写以下内容

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        void (^block)(void) = ^ {
            printf("a block");
        };
        block();
    }
    return 0;
}

查看clang中间文件

clang -rewrite-objc main.m

在这里插入图片描述

回车会在刚拖入的文件中生成.cpp文件

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

//block 结构体
//这一部分在.cpp文件中没有找到
struct __block_impl {
  void *isa;//block 的类型
  int Flags;
  int Reserved;
  void *FuncPtr;// block的执行函数指针,指向__main_block_func_0
};
                        
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

            printf("a block");
        }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
    return 0;
}

到这里,我们可以看到,在编译之前,block复原成以上四个结构体。 它们分别是:

  • __main_block_impl_0
  • __block_impl
  • __main_block_desc_0
  • __main_block_func_0

我们暂时不管这些结构体代表的都是什么。但可以说明block是结构体。仔细观察__main_block_impl_0 的机构中,有isa指针一项(黄色标出)。看到这里理解为什么苹果强调block也是一个对象了。再看还有 __main_block_func_0 ,这里其实就是我们对block函数体的实现,它实际上是一个匿名函数,作为block的众多结构体的一部分。

全局block,栈block,以及堆区block的区别和他们之间的联系,探究block的内存管理

在OC中用三种不同的block类型。它们分别是全局block _NSConcretionGlobalBlock, 栈block _NSConcretionStackBlock,以及堆block _NSConcretionMallocBlock.

全局block

假如我们这样创建一个block并使用
在这里插入图片描述

通过clang 命令获得中间编译内容

int GlobalInt = 0;

struct __getGlobalInt_block_impl_0 {
  struct __block_impl impl;
  struct __getGlobalInt_block_desc_0* Desc;
  __getGlobalInt_block_impl_0(void *fp, struct __getGlobalInt_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteGlobalBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static int __getGlobalInt_block_func_0(struct __getGlobalInt_block_impl_0 *__cself) {

    return GlobalInt;
}

static struct __getGlobalInt_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __getGlobalInt_block_desc_0_DATA = { 0, sizeof(struct __getGlobalInt_block_impl_0)};
static __getGlobalInt_block_impl_0 __global_getGlobalInt_block_impl_0((void *)__getGlobalInt_block_func_0, &__getGlobalInt_block_desc_0_DATA);
int (*getGlobalInt)(void) = ((int (*)())&__global_getGlobalInt_block_impl_0);
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_46_qzlmlhgd0xd2xjp590bfb5_00000gn_T_main_14343d_mi_0, ((int (*)(__block_impl *))((__block_impl *)getGlobalInt)->FuncPtr)((__block_impl *)getGlobalInt));
    }
    return 0;
}

_NSConcretionGlobalBlock代表这是一个全局的block。全局block和全局变量一样,可以在整个数据域中使用。 这里的其他的任何retain, copy对它是没有影响的。它存储在静态区域,基本可以理解,在APP运行期间,它是一直存在的。

很明显看到,这个block作为全局变量的形式被创建出来的。还有一种更加隐秘的方式, 像下面这样。

在这里插入图片描述

打印
在这里插入图片描述

同样是一个全局的block。

所以全局block的生成有两种不同的情况,一个是直接将block创建成一个全局变量。这是苹果官方的用法。另一种是创建一个局部变量的block,在block的函数体中,不使用任何外部的全局变量。但这个block和全局变量的block是有所不同的。我们将这个block的cpp中间文件打开。

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

            printf("a block");
        }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_46_qzlmlhgd0xd2xjp590bfb5_00000gn_T_main_c071cc_mi_0, block);
    }
    return 0;
}

竟然是 _NSConcreteStackBlock! 也即是我们所说的栈block! 这是为什么呢? 我个人的理解是,对于CPP文件中的指示,它是告诉用户这个结构体的存储的位置。 而在nslog打印中显示不一样是因为因为没有包含局部变量,所以block本身不需要携带上下文环境,系统在编译的时候,默认Block是全局环境。 这才导致两种展示的方式不一样。

栈block

刚才说了,全局block的其中创建方式是作为一个不包含外部变量的局部变量block。 那如果这个block变量包含了外部变量那又会怎样呢。没错,当包含了外部变量的时候,它是一个栈Blobk。

在这里插入图片描述

clang查看代码生成的中间文件。 发现是存在于栈中的。

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int a;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

打印结果,在ARC环境中
在这里插入图片描述

在MRC环境下
在这里插入图片描述

为什么在ARC的环境下的打印结果不同呢?

正常情况下,block的申明都是在栈中的,如果需要将它转到堆上,需要进行block_copy,或者其他发送copy消息。
如果在MRC没有进行copy的话,那么当处于栈中的block的环境被销毁的时候,block也等同被销毁了。
而在ARC中 ,因为系统会自动对block发送copy消息(原因是为了确保在块作为对象时,其生命周期得到正确管理)所以我们打印的时候看到block是mallco类型,即位于堆上的。在没有进行copy 之前,栈上的Block使用retain 等操作都是没有实际作用的。

堆上的block

block的申明的时候都是在栈上的,如果发送了copy消息,那么block才会被复制到上。

当复制到堆上之后,我们使用block就可以像使用普通的属性一样,可以进行retain等。注意,重复发送copy 消息,也只会在堆上保留一份blcok。在block所在的栈中的内容没有被销毁之前,这个栈中的block还依然存在的。但是它多了一条跟堆中block的联系。我们回过头看他的一个结构体:

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

printf(“a block”);

}

在这个block的结构体中,结构体本身的类型是__main_block_func_0 。 内部有一个参数指针指向了一个__main_block_impl_0,cself 结构体,这个指针实际上指向的是自己,如果block接受了copy 消息之后,那么这个指针将指向堆上的那份block,而堆上的那份的block的cself 还是指向堆上的blobk结构体,这就是为什么在复制到堆上之后,当栈上的内容被销毁时,block调用不会crash的原因了。

三,为什么使用_block就可以使block可以修改外部变量

我们先看一看当block对外部变量使用__block修饰局部变量前后的clang
使用前
在这里插入图片描述

clang

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int a;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int a = __cself->a; // bound by copy

            printf("%d", a);
        }```

使用后
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a25a4dc29d7b4f81a7539af9c9fe2dad.png#pic_center)

clang

```objectivec
struct __Block_byref_a_0 {
  void *__isa;
__Block_byref_a_0 *__forwarding;
 int __flags;
 int __size;
 int a;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_a_0 *a; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_a_0 *a = __cself->a; // bound by ref

            printf("%d", (a->__forwarding->a));
        }

我们可以看到区别:

当使用不加block修饰的局部变量时,直接通过__cself指针找到__main_block_impl_0结构体中自动生成的一个相同类型的age变量(为值传递),所以不能修改捕获的变量。

但使用block修饰的block变量时,通过__cself指针找到__main_block_impl_0结构体中__Block_byref_a_0 *的a结构体(_block修饰的局部变量),再在a中找到__forwarding指针,可以看到它的类型同样为__Block_byref_a_0 *类型,它指向结构体本身(block修饰的局部变量),最后通过_forwarding指针找到局部变量a本身,这样就可以进行修改外部变量。

简单讲,就是一个修改的是值传递过来的外部变量,一个是通过指针找到外部变量本身,修改实际上就是对外部变量的修改

四,引起强引用的原因是什么,我们解决的方法和原理是什么

什么情况下block会造成循环引用

block为了保证代码块内部对象不被提前释放,会对block中的对象进行强引用,就相当于持有了其中的对象,如果此时block中的对象有持有了该block,就会造成循环引用。

在这里插入图片描述

block作为self的一个属性,表明self是持有block的,这样,如果需要释放block,至少需要先把self对它的持有释放,而block是self的属性,要让self不在持有它,只有一种情况,self已经被释放。ARC会自动处理块对self的持有关系。当块被复制到堆上时,会自动将self的引用计数加1,以确保在块的生命周期内,self对象不会被提前释放,也即是持有了self.

那么这样的情况下,如果要释放self,至少要做的一件事情是让block不再持有self,显然,上面的这种情况,要不持有slef,只能等待block被销毁。 这时候,block和slef相互等待着对方先被释放,才能释放自己,一直矛盾着两个对象都得不到释放,就会造成循环引用

解决方法
1,OC提供了weak修饰符
我们会申请一个weak self对象参与block的copy使用。

在这里插入图片描述

这样就不会发生警报。

2.使用弱引用和强引用的结合
当使用__weak修饰后,如果外部对象为空了,那么block的内部对象也将为空,这样有时候并不是我们想要的。AFNetWorking中使用了一个办法解决这一问题。就是在block内部继续使用__Strong来修饰带进来的weakself。
在这里插入图片描述

这样做的好处就是避免了循环引用,同时保证对象在block中的持续存在,而不会因为block外的变量因为被释放掉使block内部的变量也为空了。

3.使用__block修饰符

在这里插入图片描述

当一个对象被__block修饰时,在块内部对该对象的引用会变为一个弱引用。这样,在块内部对该对象的使用不会阻止对象的释放,从而打破了循环引用。

需要注意的是,__block修饰符只在块内部起作用,不会改变对象在块之外的引用语义。因此,即使对象被__block修饰,如果在块外部仍然存在其他强引用,循环引用仍然可能发生。因此,使用__block修饰符时,需要综合考虑对象在块内外的引用关系,以避免潜在的循环引用问题。

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

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

相关文章

C语言基础知识巩固——1.基本知识

语言是面向过程的&#xff0c;体现为其通过函数及其调用关系来描述程序逻辑 将大问题拆解为一套流程&#xff0c;执行这套流程中的各个步骤即可&#xff1a; 每一个步骤有明确的入口和出口每一个步骤可以继续拆解为一套更细化的流程最后得到描述问题解决方案的完整逻辑 函数…

指针专题(1)

前言 指针在C语言中占据着重要的位置&#xff0c;对指针的掌握度会直接影响到编写C语言代码的能力&#xff0c;而且指针的难度较大&#xff0c;所以我们要认真的学习指针。那么废话不多说&#xff0c;我们正式进入今天的指针学习 &#xff08;PS&#xff1a;之前有关指针、结构…

前端开发攻略---Vue项目(Vue2和Vue3)引入高德地图,超详细,超简单,保姆级教程。

1、图片演示 2、引入前的准备 1、前往 高德开放平台 进行账号注册。如果手机上有高德地图App并且已经登录过&#xff0c;则可以直接选择登录 2、注册/登录完成后来到应用管理-->我的应用 3、点击创建新应用 4、填写好应用名称和选择应用类型 5、填写好后点击添加Key 6、填写…

2024.4.18

思维导图 数据库 #include <myhead.h> //添加学生信息 void insert_stu(sqlite3* sq,char* errMsg) {char text[128];int ID,age,height;char name[10];scanf("%d%s%d%d",&ID,name,&age,&height);sprintf(text,"insert into Student values …

网络运输层之(3)GRE协议

网络运输层之(3)GRE协议 Author: Once Day Date: 2024年4月8日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的…

html之标签学习(带你进来,别犹豫,是你喜欢的样子)

html之标签学习 学习 HTML 标签是创建网页的第一步&#xff0c;HTML&#xff08;Hypertext Markup Language&#xff09;是一种用于创建网页的标记语言&#xff0c;它由一系列的元素&#xff08;标签&#xff09;组成&#xff0c;每个元素都可以用来标记文档的不同部分或者给文…

仿真测试平台设计资料:921-6U CPCI卫星接口仿真测试平台

6U CPCI卫星接口仿真测试平台 一、设备概述 卫星接口仿真测试平台基于6U CPCI的结构&#xff0c;包含信号接口前板、后板&#xff0c;计算机主板、机箱、电源等硬件。硬件设计包括&#xff1a;信号接口前板、后板&#xff08;直接遥测遥控、串行RS422、LVDS&#xff0c;模拟量输…

Http 请求偶发400错误

1. 背景 生产环境偶发400请求错误&#xff0c;发生概率万分之一&#xff0c;异常信息如下&#xff1a; 1&#xff09; 从异常信息可以看到&#xff0c;skywalking的sw8 header解析失效导致异常信息。 2&#xff09; 0x0d0x0a 作为回车换行符号&#xff0c;没有被正确处理&#…

档案集中管理的痛点怎么解决?

档案集中管理可能面临的痛点包括以下几个方面&#xff1a; 1. 档案分类和整理困难&#xff1a;档案集中管理会面临大量档案的分类和整理工作&#xff0c;可能导致混乱和困难。 解决方法&#xff1a; - 建立统一的档案分类规范和流程&#xff0c;确保所有档案都能按照规定的方式…

【赛题】2024年“华中杯”数模竞赛赛题发布

2024年"华中杯"数学建模网络挑战赛——正式开赛&#xff01;&#xff01;&#xff01; 赛题已发布&#xff0c;后续无偿分享各题的解题思路、参考文献&#xff0c;帮助大家最快时间&#xff0c;选择最适合是自己的赛题。祝大家都能取得一个好成绩&#xff0c;加油&a…

Rust腐蚀服务器插件安装教程

Rust腐蚀服务器插件安装教程 大家好我是艾西&#xff0c;一个做服务器租用的网络架构师。之前教大家怎么搭建Rust腐蚀服务器&#xff0c;那么很多小伙伴在搭建完成后发现自己的游戏跟平台玩的还是有差别&#xff0c;其实这里主要缺少mod插件了。那么本期我们教一下大家mod插件…

Swagger接口文档 —— 手把手教学,全方位超详细小白能看懂,百分百能用Java版

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对博主首页也很感兴趣o (ˉ▽ˉ&#xff1b;) 博主首页&#xff0c;更多redis、java等优质好文以及各种保姆级教程等您挖掘&#xff01; 目录 一、介绍 二、导入依赖 三、在配置类中加入 knife4j 相关…

图像分割:Pytorch实现UNet++进行医学细胞分割

图像分割&#xff1a;Pytorch实现UNet进行医学细胞分割 前言相关介绍项目结构具体步骤准备数据集读取数据集设置并解析相关参数定义网络模型定义损失函数定义优化器训练验证 参考 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#x…

应急响应-战中反制对抗上线CSGoby蚁剑Sqlmap等安全工具

知识点 战中-反制-安全工具篇CS反制(有版本限制) Goby反制&#xff08;有版本限制&#xff0c;新版goby已修复&#xff09; Antsword反制(有版本限制&#xff0c;别人也不一定用蚁剑) AWVS反制(有版本限制&#xff0c;在awvs 10版本存在&#xff09; BURP反制(有版本限制&…

git 删除本地分支 删除远程仓库中的分支

语法&#xff1a; 删除本地分支 git branch -D <分支名>删除远程分支 git push <remote名称> <分支名> --delete 示例&#xff1a; 删除本地分支 git branch -D feature/test_listview删除远程分支 git push origin feature/test_listview --delete 两个…

【计算机组成原理】加法器原理及其优化

苏泽 本专栏纯个人笔记作用 用于记录408 学习的笔记记录&#xff08;敲了两年码实在不习惯手写笔记了&#xff09; 如果能帮助到大家当然最好 但由于是工作后退下来备考 很多说法和想法都会结合实际开发的思想 可能不是那么的纯粹应试哈 希望大家挑选自己喜欢的口味食用…

推荐一个靠谱稳定适合单位和个人的媒体投稿平台

身为单位的信息宣传员,我肩负着每月完成对外信息宣传考核任务的重任。在这条道路上,我经历了从之初摸着石头过河,一家家联系媒体的艰辛,到如今使用智慧软文发布系统网站进行投稿发文章的轻松转变。 记得刚开始的时候,我对媒体投稿一窍不通。每次都要花费大量时间去搜索各种媒体…

Avi Wigderson:理论计算机科学的巨人

&#x1f3c6;个人专栏 &#x1f93a; leetcode &#x1f9d7; Leetcode Prime &#x1f3c7; Golang20天教程 &#x1f6b4;‍♂️ Java问题收集园地 &#x1f40d; Python工具 &#x1f334; 成长感悟 欢迎大家观看&#xff0c;不执着于追求顶峰&#xff0c;只享受探索过程 A…

【Kafka】Kafka Tool工具的使用

抖音视频 https://www.douyin.com/user/self?modal_id7123007128150901256&showTablike CSDN文档 https://blog.csdn.net/qq_43961619/article/details/109381849

WordPress JS Support Ticket插件 RCE漏洞复现

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。JS Support Ticket是使用在其中的一套开源票务系统插件。 0x02 漏洞概述 WordPress中的JS Support Ticket插件存在未经上传漏洞,未经身份验证的攻击者可以上传恶意脚本的服务器,执行任意指令,从而获…