【iOS】属性关键字
文章目录
- 前言
- 一、深拷贝与浅拷贝
- 1、OC的拷贝方式有哪些
- 2. OC对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝?
- 3. 自定义对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝?
- 4. 判断当前的深拷贝的类型?(区别是单层深拷贝还是完全深拷贝),2种深拷贝类型的相互转换?
- 5. 代码如下所示:既然对象的mutableCopy是深拷贝,那为什么更改dataArray2,dataArray3也发生了改变?如何解决这个问题?
- 6. 代码如下图所示:initWithArray:copyItems:YES 仅仅能进行一层深拷贝,对于第二层或者更多层的就无效了。如果想要对象每层都是深拷贝,该怎么做?
- 二、属性关键字
- @property
- @synthesize
- @dynamic
- 原子操作
- atomic
- nonatomic
- 读写权限
- readwrite
- readonly
- 内存管理
- weak
- assign
- assign和weak的比较
- retain
- strong
- copy
- strong与copy的区别
- strong和copy关键字的用法
- 1. 常用的基本类型对应Foundation数据类型?
- 2. 定义属性的格式?(定义属性时修饰符的顺序?)
- 3. ARC下@property的默认属性?
- 4. 属性的读写权限关键字的含义?
- 5. 属性的原子操作关键字的含义?
- 6、delegate应该使用哪种关键字修饰?
- 7、以下属性的声明有什么问题?如果一定要这么定义,如何修改成正确的呢?
- 8、为什么@property属性用copy修饰不可变对象,而用strong修饰可变对象呢?
- 总结
前言
先前已经在iOS的学习过程中学习了一些属性关键词的简单用法,今天这篇博客来更加深入探讨iOS中的属性关键字以及温习深拷贝与浅拷贝
一、深拷贝与浅拷贝
1、OC的拷贝方式有哪些
OC对象(集合类型和非集合类型)有2种拷贝方式,分别为浅拷贝和深拷贝。
- 浅拷贝:指针拷贝,即源对象和副本对象的指针指向了同一个区域。
- 深拷贝:内容拷贝,即源对象和副本对象的指针分别指向不同的两块区域。
深拷贝包括了单层深拷贝和完全深拷贝。具体后面会有讲到
- 单层深拷贝:对于副本对象本身这一层是深拷贝,它里面的所有对象都是浅拷贝。
- 完全深拷贝:对于副本对象本身以及它里面的所有对象都是深拷贝。
浅拷贝和深拷贝的区别:
- 是否开辟了新的内存空间
- 是否影响了引用计数
2. OC对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝?
- 可变对象(集合类型/非集合类型)的copy和mutableCopy都是深拷贝。
- 不可变对象(集合类型/非集合类型)的copy是浅拷贝,mutableCopy是深拷贝。
- copy方法返回的都是不可变对象。
具体实现过程在之前博客中已经给出:【iOS】深拷贝与浅拷贝
3. 自定义对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝?
- 自定义对象实现copy和mutableCopy都为深拷贝
因为我们的自定义对象没有copyWithZone:和mutableCopyWithZone:两个方法,需要遵守SCopying和NSMutableCopying协议来实现这两个方法,也已经在上面的链接中具体实现
4. 判断当前的深拷贝的类型?(区别是单层深拷贝还是完全深拷贝),2种深拷贝类型的相互转换?
在这里我们讨论的深拷贝的类型都是对于容器类对象来讲的,因为对于非容器类对象我们并没有单层深拷贝与完全深拷贝的区分
- 单层深拷贝:对于副本对象本身是深拷贝,但是容器中的所有对象都是浅拷贝
- 完全深拷贝:对于副本对象本身与其里面的所有对象都是深拷贝
实现方式:
- 单层深拷贝:
当容器类对象中的对象是容器类对象时,使用initWithArray:copyItems:方法(第二个参数设置为YES)可以实现单层浅拷贝,因为这种拷贝只能产生一层深拷贝,对于第二层或者更多层的就无效了。 - 完全深拷贝:
1、归档和解档来实现完全深拷贝。
举例:dataArray3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray2]]
2、当容器类对象中的对象是自定义对象或不为immutable对象,使用initWithArray:copyItems:方法(第二个参数设置为YES)可以实现完全深拷贝
这里其实也很好理解,因为我们实现自定义对象的copy时我们是需要自己实现我们的copyWithZone:和mutableCopyWithZone:两个方法,而自定义对象的拷贝始终都是深拷贝,因此通过这个方法可以实现完全深拷贝
5. 代码如下所示:既然对象的mutableCopy是深拷贝,那为什么更改dataArray2,dataArray3也发生了改变?如何解决这个问题?
问题(1). 对象的mutableCopy是深拷贝,那为什么更改dataArray2,dataArray3也发生了改变?
dataArray3 = [dataArray2 mutableCopy];
这段代码实现的是单层深拷贝,dataArray3是dataArray2深拷贝得到的数组,但是对于array2数组中的对象array仅仅对其进行了浅拷贝,因此更改array2时array3随之改变
问题(2). 如何解决这个问题?
因为更改的对象非immutable对象,所以使用initWithArray:copyItems:方法可以实现完全深拷贝可以轻松解决这个问题
dataArray3 = [[NSMutableArray alloc] initWithArray:dataArray2 copyItems:YES];
6. 代码如下图所示:initWithArray:copyItems:YES 仅仅能进行一层深拷贝,对于第二层或者更多层的就无效了。如果想要对象每层都是深拷贝,该怎么做?
使用initWithArray:copyItems:实现深拷贝仅能产生一层深拷贝,再多就没有办法实现深拷贝了,所以就需要用到解档与归档
dataArray3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray2]];
二、属性关键字
@property
属性用于封装对象中的数据,属性的本质是 ivar + setter + getter。
可以用 @property 语法来声明属性。@property 会帮我们自动生成属性的 setter 和 getter 方法的声明。
@synthesize
帮我们自动生成 setter 和 getter 方法的实现以及合成实例变量。
@dynamic
告诉编译器不用自动进行 @synthesize,你会在运行时再提供这些方法的实现,无需产生警告,但是它不会影响 @property 生成的 setter 和 getter 方法的声明。
@dynamic ivar;
以前我们需要手动对每个 @property 添加 @synthesize,而在 iOS 6 之后 LLVM 编译器引入了 property autosynthesis,即属性自动合成。换句话说,就是编译器会自动为每个 @property 添加 @synthesize。
但是这样看来似乎@synthesize就没有什么用了,其实不然:
- 如果我们重写了setter 和 getter 方法,则编译器就不会自动为这个 @property 添加 @synthesize,所以我们需要手动添加 @synthesize;
- 如果该属性是 readonly,那么只要你重写了 getter 方法,property autosynthesis 就不会执行
- 另外就是实现协议中要求的属性。当我们在协议中使用@property声明一个属性,在某个类中遵循这个协议,我们就必要在类中使用@synthesize来获取这个属性的成员变量,并且得到其set/get的实现函数
这里说到了协议,那么我们再来讨论一下Category是否能够添加使用@synthesize来合成成员变量以及实现setget方法呢?
答案是并不行,在我们的Category中我们可以声明属性,但不能声明成员变量
因为分类不是类,我们可以通过@property声明属性,但是并不能声明成员变量
Category是用来扩展现有类的功能的,而不是创建全新的类或修改类的内部实现。因此,Category不允许添加实例变量(成员变量)或使用@synthesize来合成成员变量。
以下笔者将一下为什么Category不能添加实例变量和使用@synthesize的原因:
- 我们的实例变量的声明我们通常需要放在类的文件中,以确保封装性,而因为分类不是类,Category只能添加方法和属性的声明,因此不允许添加实例变量,因为这会破坏类的封装性。
- 当我们使用@synthesize来合成成员变量时,编译器会自动生成对应的实例变量,由于Category不能添加实例变量,编译器无法为Category中的属性生成对应的实例变量,因此不允许使用@synthesize。
使用 @synthesize 关键字会合成属性的实例变量以及属性的 getter 和 setter 方法
这是我们从代码使用的层面上分析Category不能使用@synthesize的原因,接下来我们从底层结构的层面分析一下原因:
分类是在运行时去把分类中的方法添加到类的方法列表里,类的底层其实是结构体,分类可以添加属性,不能添加成员变量,因为结构体声明后不能加成员变量,而属性是结构体里的一个列表(rw:property_array_t / ro: property_list_t),就是可以加的。
而分类当中不能添加成员变量,只能通过关联对象间接实现分类有成员变量的效果,这个知识点笔者还没能理解,后面学到了加以补充
原子操作
原子操作:属性是否有原子性可以理解为线程是否安全。
原子性,加同步锁,默认修饰符。 使用atomic会损耗性能,也不一定保证线程安全。如果保证线程安全需要使用其他锁机制。
非原子性,不实用同步锁。 声明属性时基本设置为nonatomic。使用nonatomic能够提高访问性能。
这里笔者还没学到锁的相关知识,等学到了再加以补充
读写权限
读写权限不写时默认为 readwrite
属性拥有setter方法和getter方法
仅有getter方法
内存管理
内存管理相关的关键词我们也可以理解为setter相关控制符,setter相关的修饰符表明setter方法应该如何实现
weak
- 只能修饰对象类型;
- ARC 下才能使用;
- 修饰弱引用,不增加对象引用计数,主要可以用于避免循环引用;
- weak 修饰的对象在被释放之后,会自动将指针置为 nil,不会产生悬垂指针;
- 对于视图,通常还是用在 xib 和 storyboard 上;代码中对于有必要进行 remove 的视图也可以使用 weak,这样 remove 之后会自动置为 nil。
assign
- 既可以修饰基本数据类型,也可以修饰对象类型;
- setter 方法的实现是直接赋值,一般用于基本数据类型 ;
- 修饰基本数据类型,如 NSInteger、BOOL、int、float 等;
- 修饰对象类型时,不增加其引用计数;
- 会产生悬垂指针(悬垂指针:assign 修饰的对象在被释放之后,指针仍然指向原对象地址,该指针变为悬垂指针。这时候如果继续通过该指针访问原对象的话,就可能导致程序崩溃)。
assign和weak的比较
相同点:对对象的引用计数没有影响,即都是弱引用。
不同点:
- 修饰的对象类型不同:
weak只能修饰OC对象(如UIButton、UIView等)。
assign可以修饰基本数据类型(NSInteger、NSUInteger、CGFloat、NSTimeInterval、int、float、BOOL等)和OC对象(如果用assign修饰OC对象,对象销毁时可能会产生悬垂指针,从而出现crash,不要这么做)。
注意: 使用assign修饰OC对象可能会导致程序crash,所以assign最好只用来修饰基本数据类型。
- 赋值的方式不同:weak复制引用,assign复制数据。
- 对象销毁后的状态不同:weak自动为nil,assign不变。
retain
- MRC 下使用,ARC 下基本使用 strong;
- 修饰强引用,保留新值,释放旧值,再设置新值,同时将新对象的引用计数加 1;
- setter 方法的实现是 release 旧值,retain 新值,用于 OC 对象类型。
我们这里详细解释一下保留新值,释放旧值,再设置新值:
strong
- ARC 下才能使用;
- 原理同 retain;
- 但是在修饰 block 时,strong 相当于 copy,而 retain 相当于 assign。
copy
setter 方法的实现是 release 旧值,copy 新值
一般用于 block、NSString、NSArray、NSDictionary 等类型。使用 copy 或 strong 修饰 block 其实都一样,用 copy 是为了和 MRC 下保持一致的写法;用于 NSString、NSArray、NSDictionary 是为了保证赋值后是一个不可变对象,以免遭外部修改而导致不可预期的结果。
当你使用copy特性来声明一个属性时,这意味着当设置属性时,属性会复制传入的对象,而不仅仅是保持对传入对象的引用。这通常用于确保属性拥有自己的独立副本,以避免不经意的更改。
下面是一个示例:
@property (nonatomic, copy) NSString *name;
在上面的代码中,name属性使用了copy特性。当你设置name属性时,传入的字符串会被复制,而不是保留对原始字符串的引用。这意味着如果原始字符串在后续被修改,name属性的值不会受到影响。
合成的存取方法会自动处理这个行为。例如,如果你设置self.name = @“Alice”,name属性会将传入的字符串@"Alice"复制为自己的副本,而不仅仅是保存对@"Alice"的引用。
strong与copy的区别
如果属性声明中指定了copy特性,合成方法会使用类的copy方法,这里注意:属性并没有mutableCopy特性。即使是可变的实例变量,也是使用copy特性,正如方法 copyWithZone:的执行结果。所以,按照约定会生成一个对象的不可变副本。
- 相同之处:用于修饰标识拥有关系的对象
- 不同之处:strong的赋值是多个指针指向同一个地址,而copy的复制就是每次会在内存中复制一份对象,指针指向不同的地址。
所有对于不可变对象我们应该使用copy修饰,为确保对象中的字符串值不会无意变动,应该在设置新属性时拷贝一份
再通俗一点的理解就是用strong修饰属性并对其进行赋值时可以理解为指针拷贝,而用copy修饰时可以理解为内容拷贝
我们来给出代码的例子:
- strong修饰
NSMutableString *otherName = [[NSMutableString alloc] initWithString:@"Jack"];
Person *person = [[Person alloc] init];
person.name = otherName;
person.age = 23;[otherName appendString:@" and Mary"];
NSLog(@"person.name = %@",person.name);
NSLog(@"%p, %p", person.name, otherName);
我们分别打印属性以及属性的地址与原始对象的地址:
可以看到我们的属性是可以被修改的,并且属性的地址与原始对象的地址相同,说明用strong修饰属性时,属性指向原对象的内存地址,同时使该对象引用计数加1
- copy修饰
NSMutableString *otherName = [[NSMutableString alloc] initWithString:@"Jack"];
Person *person = [[Person alloc] init];
person.name = otherName;
person.age = 23;[otherName appendString:@" and Mary"];
NSLog(@"person.name = %@",person.name);
NSLog(@"person.name = %@",otherName);
NSLog(@"%p, %p", person.name, otherName);
当我们属性修饰改为copy时,打印出的结果如下图所示:
可以看到我们属性指向的地址与原始对象的地址不同,并且我们的属性指向的内存空间的数据并未被修改,但是原对象的数据被修改了,说明用copy进行修饰属性对其进行赋值时会创建一块新的内存空间,属性指向新创建的内存空间,本质其实就是内容拷贝(深拷贝)
strong和copy关键字的用法
@property属性用copy修饰不可变对象,用strong修饰可变对象。
1. 常用的基本类型对应Foundation数据类型?
在声明一个属性时,尽量使用Foundation框架的数据类型,使代码的数据类型更统一。
基本类型和Foundation数据类型的对应关系如下:
- int -> NSInteger
- unsigned -> NSUInteger
- float -> CGFloat
- 动画时间 -> NSTimeInterval
2. 定义属性的格式?(定义属性时修饰符的顺序?)
推荐按照下面的格式来定义属性
@property (nonatomic, readwrite, copy) NSString *name;
属性的修饰符应该按照上面的顺序排列:原子操作、读写权限、内存管理。
3. ARC下@property的默认属性?
对于基本数据类型:atomic、readwrite、assign
对于普通的Objective-C对象:atomic、readwrite、strong
4. 属性的读写权限关键字的含义?
读写权限
readwrite:可读可写,默认修饰符。会自动生成getter和setter。
readonly:只读。只会生成getter而不生成setter。
5. 属性的原子操作关键字的含义?
原子操作:属性是否有原子性可以理解为线程是否安全。
atomic:原子性,加同步锁,默认修饰符。
使用atomic会损耗性能,也不一定保证线程安全。如果保证线程安全需要使用其他锁机制。
nonatomic:非原子性,不实用同步锁。
声明属性时基本设置为nonatomic。使用nonatomic能够提高访问性能。
这里设计到了一些锁的知识,还没有学到,后面学到再进行补充
6、delegate应该使用哪种关键字修饰?
MRC时期:使用assign,这样不会造成循环引用,但是需要手动释放。
ARC时期:最好使用weak,如果使⽤了assign需要⼿动释放。如果没写释放逻辑,当⻚面销毁的时候,很可能出现delegate对象无效,导致程序crash。
7、以下属性的声明有什么问题?如果一定要这么定义,如何修改成正确的呢?
@property (nonatomic, copy) NSMutableArray *mutableArray;
如果我们对属性进行增删改等操作时,程序会崩溃,因为当我们对属性进行赋值时,copy复制的是一个不可变的NSArray对象
具体分析:不应该使用copy关键字来修饰可变对象。
copy修饰的属性会在内存里拷贝一份对象,即两个指针指向不同的内存地址。
Foundation框架提供的可变对象类型都已实现了NSCopying协议,所以使用copy方法返回的都是不可变对象。
本题中,用copy关键字修饰了可变数组,那么当对该属性赋值时会得到一个NSArray类型的不可变数组。
因为是NSArray类型,即是不可变的数组类型,所以如果对属性进⾏了可变数组的增删改功能都会导致crash。
所以正确写法如下
@property (nonatomic, strong) NSMutableArray *mutableArray;
如果一定要用copy,我们需要重写setter方法,因为对当属性用copy修饰进行赋值时,会自动调用setter方法执行copyWithZone:方法,返回的是不可变对象,所以我们需要对待吗进行如下修改:
// .h文件
@property (nonatomic, copy) NSMutableArray *mutableArray;// .m文件
// 重写setter⽅法 使_mutableArray变为可变的copy
- (void)setMutableArray:(NSMutableArray *)mutableArray {_mutableArray = [mutableArray mutableCopy];
}- (void )viewDidLoad { [super viewDidLoad];NSMutableArray *array = [NSMutableArray arrayWithObjects:@1, @2, nil]; self.mutableArray = array;[self.mutableArray removeObjectAtIndex:0]; NSLog(@"self.mutableArray:%@", self.mutableArray);
}输出:
self.mutableArray:( 2
)
8、为什么@property属性用copy修饰不可变对象,而用strong修饰可变对象呢?
- 用copy修饰不可变对象:
copy修饰的属性会在内存里拷贝一份对象,即两个指针指向不同的内存地址。
Foundation框架提供的对象类型都已实现了NSCopying协议,所以使用copy方法返回的都是不可变对象。
即使源对象是可变对象(实现属性所用的对象是mutable),copy后的对象也不会随之改变。
确保了对象不会无意间被改动。
- 用strong修饰可变对象:
strong修饰的属性是对属性进行了强引用,即两个指针会指向同一个内存地址。
如果源对象可变,strong修饰的对象也会随之改变。
总结
属性关键字的细节还有很多很多,后面学到更多的知识会加以补充
相关文章:

【iOS】属性关键字
文章目录 前言一、深拷贝与浅拷贝1、OC的拷贝方式有哪些2. OC对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝?3. 自定义对象实现的copy和mutableCopy分别为浅拷贝还是深拷贝?4. 判断当前的深拷贝的类型?(区别是单层深拷贝还是完全深拷贝…...

【计算机基础】Git从安装到使用,详细每一步!扩展Github\Gitlab
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...

深入了解Docker镜像操作
Docker是一种流行的容器化平台,它允许开发者将应用程序及其依赖项打包成容器,以便在不同环境中轻松部署和运行。在Docker中,镜像是构建容器的基础,有些家人们可能在服务器上对docker镜像的操作命令不是很熟悉,本文将深…...

嵌入式开发-单片机学习介绍
一、单片机入门篇 单片机的定义和历史 单片机是一种集成了微处理器、存储器、输入输出接口和其他功能于一体的微型计算机,具有高度的集成性和便携性。单片机的历史可以追溯到20世纪70年代,随着微电子技术的不断发展,单片机逐渐成为了工业控…...

5、Spring之Bean生命周期源码解析(销毁)
Bean的销毁过程 Bean销毁是发送在Spring容器关闭过程中的。 在Spring容器关闭时,比如: AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserService userService = (UserService) context.getBean("userSe…...

开发多点触控MFC应用程序
当下计算机变得越来越智能化,越来越无所不能,触摸屏的普及只是时间问题了。 虽然鼠标和键盘不会很快就离开人们的视野,毕竟人们使用鼠标跟键盘已经成为一种习惯,但是处理信息或者说操作计算机的其他方法也层出不穷——比如触控技术…...

使用nlohmann json库进行序列化与反序列化
nlohmann源码仓库:https://github.com/nlohmann/json使用方式:将其nlohmann文件夹加入,包含其头文件json.hpp即可demo #include <iostream> #include "nlohmann/json.hpp" #include <vector>using json nlohmann::js…...

高教社杯数模竞赛特辑论文篇-2012年A题:葡萄酒的评价(附获奖论文)
目录 摘 要 一、问题重述 二、问题分析 2.1 问题一的分析 2.2 问题二的分析...

手写RPC——数据序列化工具protobuf
手写RPC——数据序列化工具protobuf Protocol Buffers(protobuf)是一种用于结构化数据序列化的开源库和协议。下面是 protobuf 的一些优点和缺点: 优点: 高效的序列化和反序列化:protobuf 使用二进制编码,…...

【MATLAB第70期】基于MATLAB的LightGbm(LGBM)梯度增强决策树多输入单输出回归预测及多分类预测模型(全网首发)
【MATLAB第70期】基于MATLAB的LightGbm(LGBM)梯度增强决策树多输入单输出回归预测及多分类预测模型(全网首发) 一、学习资料 (LGBM)是一种基于梯度增强决策树(GBDT)算法。 本次研究三个内容,分别是回归预测,二分类预测和多分类预…...

Linux进程间通信的几种方式
分析&回答 管道(pipe)以及有名管道:管道可用于有亲缘关系进程间通信,有名管道克服了管道没有名字的限制,因此具有管道的所有功能之外,它还允许无亲缘关系进程间通信。信号(Signalÿ…...

Android 13.0 Launcher3定制之双层改单层(去掉抽屉式一)
1.概述 在13.0的系统产品开发中,对于在Launcher3中的抽屉模式也就是双层模式,在系统原生的Launcher3中就是双层抽屉模式的, 但是在通过抽屉上滑的模式拉出app列表页,但是在一些产品开发中,对于单层模式的Launcher3的产品模式也是常用的功能, 所以需要了解抽屉模式,然后修…...

【uniapp 配置启动页面隐私弹窗】
为什么需要配置 原因 根据工业和信息化部关于开展APP侵害用户权益专项整治要求,App提交到应用市场必须满足以下条件: 1.应用启动运行时需弹出隐私政策协议,说明应用采集用户数据 2.应用不能强制要求用户授予权限,即不能“不给权…...

2分钟讲清楚C#的委托, C语言的函数指针,Java的函数式接口
很多小伙伴学习C# 的委托时往往一头雾水, 不明白委托是什么, 有什么作用, 今天我就用2分钟讲清楚 这是一个C# 的控制台程序 定义一个最简单的委托 delegate int Calculate(int a, int b); 这相当于定义了一个Calculate类型, 只不过这个类型需要传入2个int类型的参数 返回值也…...

华为云物联网平台微信小程序开发教程2.0【完整详细教程】
一、简介 在之前曾发布过一篇文章“华为云物联网平台的微信小程序开发”,在最近接到部分用户私信在使用开发过程中出现的问题,例如API访问的"401"现象等问题,在重新查看上面的文章教程时发现教程内容的步骤不详细,现对教…...

Laravel 模型1对1关联 1对多关联 多对多关联 ⑩①
作者 : SYFStrive 博客首页 : HomePage 📜: THINK PHP 📌:个人社区(欢迎大佬们加入) 👉:社区链接🔗 📌:觉得文章不错可以点点关注 ὄ…...

【分类】分类性能评价
评价指标 1、准确率、召回率、精确率、F-度量、ROC 属于各类的样本的并不是均一分布,甚至其出现概率相差很多个数量级,这种分类问题称为不平衡类问题。在不平衡类问题中,准确率并没有多大意义,我们需要一些别的指标。 通…...

M1 Pro 新芯片安装python2 方案汇总
前言:磨刀不误砍柴工,环境装好,才能打工。M1 Pro 新芯片安装python2 文章目录 方案一 docker 容器构造环境(如果涉及本地两个仓库需要关联则不适用)方案二 使用 pyenv 🚀 作者简介:作为某云服务…...

无涯教程-Android - Broadcast Receivers
Broadcast Receivers 仅响应来自其他应用程序或系统本身的广播消息,这些消息有时称为events或intents。例如,应用程序还可以启动广播,以使其他应用程序知道某些数据已下载到设备并可供他们使用,因此广播接收器将拦截此通信并启动适…...

【Pytorch】Tutorials个人翻译集合
本文记录Pytorch Tutorials文档的翻译文章集合. 由于本人英语能力有限(only-CET4),欢迎指正翻译中的错误。 Introduction to PyTorch 【Pytorch】Pytorch文档学习1:Tensors 【Pytorch】Pytorch文档学习2:DATASETS &a…...

WordPress(6)网站侧边栏倒计时进度小工具
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 效果图在这里插入图片描述一、添加位置二、主题style.css文件中添加美化1.引入库2.添加自定义的HTML模块效果图 提示:以下是本篇文章正文内容,下面案例可供参考 一、添加位置 在主题中 child.js…...

uniapp小程序单页面改变手机电量,头部通知的颜色效果demo(整理)
onShow(){ // 改变电池的颜色 wx.setNavigationBarColor({ frontColor: ‘#ffffff’, //只支持两种颜色 backgroundColor: ‘#ffffff’, animation: { duration: 1 } }) }...

数据挖掘导论学习笔记1(第1 、2章)
参考:https://blog.csdn.net/u013232035/article/details/48281659?spm1001.2014.3001.5506 和《数据挖掘导论》学习笔记(第1-2章)_时机性样本_schdut的博客-CSDN博客 第1章 绪论 数据挖掘是一种技术,它将传统的数据分析方法…...

从零开始,探索C语言中的字符串
字符串 1. 前言2. 预备知识2.1 字符2.2 字符数组 3. 什么是字符串4. \04.1 \0是什么4.2 \0的作用4.2.1 打印字符串4.2.2 求字符串长度 1. 前言 大家好,我是努力学习游泳的鱼。你已经学会了如何使用变量和常量,也知道了字符的概念。但是你可能还不了解由…...

Ubuntu学习---跟着绍发学linux课程记录(第二部分)
文章目录 7 文件权限7.1 文件的权限7.2 修改文件权限7.3 修改文件的属主 8、可执行脚本8.2Shell脚本8.3python脚本的创建 9Shell9.1Shell中的变量9.2 环境变量9.3用户环境变量 学习链接: Ubuntu 21.04乌班图 Linux使用教程_60集Linux课程 所有资料在 http://afanihao.cn/java …...

React18 新特性
React18 新特性 自动批量更新State 定义 import { useState } from reactconst [x, setX] useState(0)渲染赋值 setX(5)并发CM模式 同步不可中断更新机制 -> 异步可中断并行 状态更新 机制 React18 默认开启并发模式 详见代码 ReactDOM 的引入 import ReactDOM fr…...

HarmonyOS Codelab 优秀样例——购物应用,体验一次开发多端部署魅力
一. 样例介绍 本篇Codelab基于自适应布局和响应式布局,实现购物应用在手机、折叠屏、平板不同屏幕尺寸设备上按不同设计显示。通过三层工程结构组织代码,实现一次开发,多端部署 。 手机运行效果如图所示: 折叠屏运行效果图&#x…...

音频基本知识
声音传播方式: 1)声音的传播需要介质,在真空中不能传播; 2)声波属于纵波,即如下图传播方向与振动方向一致; 声音速度: 1)常温常压下,一般空气速度为340m/s; 2)温度越高,声速越大; 3)液体、固体的传播速度比空气快; 人耳可接收到的频域范围: 1)通常范围…...

小程序中如何给会员卡设置到期时间
通过设置会员卡到期时间,可以有效地管理会员卡的使用周期,提供更好的会员服务体验。下面将介绍一种常见的给会员卡设置到期时间的方法。 1. 找到指定的会员卡。在管理员后台->会员管理处,找到需要设置到期时间的会员卡。也支持对会员卡按…...

Cookie与Session的区别及如何选择
目录 Cookie Session 如何选择 在网站开发中,Cookie与Session是两种常见的数据管理方式,它们在不同情况下有各自的优势和劣势。在这篇文章中,我们将深入了解Cookie与Session之间的区别,并提供了一些建议,帮助您在实…...