【iOS】KVC
文章目录
KVC的定义
容器类中KVC的实现
KVC设值
KVC取值
KVC使用KeyPath
KVC处理异常
KVC处理设值nil异常
KVC处理UndefinedKey异常
KVC处理数值和结构体类型属性
KVC键值验证
KVC处理集合
简单集合运算符
对象运算符
KVC处理字典
KVC应用
动态地取值和设值
用KVC来访问和修改私有变量
Model和字典转换
修改一些控件的内部属性
操作集合
用KVC实现高阶消息传递
实现KVO
KVC的定义
定义:KVC(Key-value coding)键值编码,是指iOS开发中,允许开发者通过key名直接访问对象的属性,或者给对象的属性赋值,而不需要调用明确的存取方法。使用KVC键值编码的好处就是可以在运行时动态地访问和修改对象的属性,而不是在编译时确定。
注意:在实现了访问器方法的类中,使用点语法和KVC访问对象差别不大,二者可以混用。但是在没有访问器方法的类中,无法使用点语法,这时KVC就有优势了。
KVC的定义都是对NSObject的扩展来实现的,OC语言中有一个显示的NSKeyValueCoding类别名,所以所有继承了NSObject的类型,都能使用KVC(一些没有继承NSObject的纯Swift类和结构体不支持KVC),下面是KVC最重要的四个方法:
- (nullable id)valueForKey:(NSString *)key;//直接通过Key来取值
- (void)setValue:(nullable id)value forKey:(NSString *)key;//通过Key来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;//通过KeyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;//通过KeyPath来设值
此外,在NSKeyValueCoding这个类别中,还有一些其他的方法:
+ (BOOL)accessInstanceVariablesDirectly;
//默认返回YES,表示如果没有找到Set<Key>这个存取方法的话,会按照_key, _iskey, key, iskey的顺序搜索成员,重写方法设置成返回NO就不会这样搜索,也就是说如果没找到Set<Key>这个方法,就不会再继续搜索
- (BOOL)validateValue:(inout id __nullable * __)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//KVC提供属性值正确性验证的API,可以用来检查set的值是否正确,为不正确的值做一个替换值或者拒绝设置新值并返回错误原因(通过outError参数来返回错误原因)
- (NSMutableArray *)mutableArrayValueForKey:(NSString*)key;
//集合操作的API,如果属性是一个NSMutableArray,那么可以用这个方法来返回这个NSMutableArray,在类别里面还有类似的API来对set操作
- (nullable id)valueForUndefinedKey:(NSString *)key;
//如果key不存在,且KVC无法搜索到任何和key有关的字段或属性,则会调用这个方法,默认抛出异常
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//这个方法也是针对key不存在的情况进行的操作,不过这个方法是在设值时操作
- (void)setNilValueForKey:(NSString *)key;
//如果在SetValue时,为方法传入的参数是nil(也就是说给Value传一个nil),就会调用这个方法
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
//输入一组key,返回该组key对应的value,再转回字典返回
关于validateValue:ioValue forKey:in**Key error:outError 这个方法,这里给出一个使用的示例,可以使用这个方法来对设置的属性值进行验证,这里以验证是否为空为例
首先在自定义的类中实现这个方法:
- (BOOL)validateValue:(inout id __nullable *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError {// 检查键名if ([inKey isEqualToString:@"name"]) {NSString *name = (NSString *)*ioValue;// 验证值是否为空if (name.length == 0) {if (outError) {*outError = [NSError errorWithDomain:@"MyDomain"code:1001userInfo:@{NSLocalizedDescriptionKey: @"Name cannot be empty."}];}return NO; // 验证失败}}return YES; // 验证成功
}
然后在设置属性值时,调用此方法进行验证:
NSError *error = nil;
NSString *name = @"";
if (![self validateValue:&name forKey:@"name" error:&error]) {NSLog(@"Validation failed: %@", error.localizedDescription);
} else {self.name = name; // 设置有效的值
}
容器类中KVC的实现
在自定义容器类时,KVC有特殊的实现
苹果原生的容器类比如NSArray或者NSSet等,都已经实现了对应的方法。
对于有序集合:
-countOf<Key> //必须实现,对应NSArray的方法count:
-objectIn<Key>AtIndex: -<Key>AtIndexes: //这两个方法必须实现一个,对应NSArray的方法objectAtIndex: 和objectsAtIndexes:
-get<Key>:range: //不是必须实现,对应NSArray方法getObjects:range:
-insertObject:in<Key>AtIndex: -insert<Key>:atIndexes: //两个必须实现一个,类似NSMutableArray的方法insertObject: atIndex: 和insertObjects: atIndexes:
-replaceObejctIn<Key>AtIndex: withObject:
-replace<Key>AtIndexes: with<Key>://可选的,是一种替换元素的方法
对于无序集合:
-countOf<Key> //必须实现,对应NSSet
-objectIn<Key>AtIndex: //由于NSSet是无序的,此方法可以选择性实现
-<Key>AtIndexes: //和上一个方法一样,选择性实现
-get<Key>: range: //不是必须实现,对应NSArray的getObjects: range:方法,无序一般不适用
-insertObject:in<Key>AtIndex: //无序集合一般不支持索引插入
-insert<Key>:atIndexes: //和上一个方法一样
-removeObjectFrom<Key>AtIndex: //和前两个一样
-remove<Key>AtIndexes: //和之前一样
-replaceObejctIn<Key>AtIndex: withObject:
-replace<Key>AtIndexes: with<Key>: //都和之前一样
一上就是KVC的定义和KVC有关的一些方法
KVC设值
通过KVC设值时,会在对象中寻找对应的key,当调用setValue: forKey:时,有一个寻找key的顺序:
-
优先调用setKey: ,通过setter方法完成设置。
-
如果未找到setKey:方法,会先检查+ (BOOL)accessInstanceVariablesDirectly方法有没有返回YES,默认返回YES,如果重写该方法返回NO的话,那么这一步KVC会执行setValue: forUndefinedKey: 方法。如果返回YES,会在该类里面搜索有没有名为_key的成员变量,无论该变量是在类接口定义,还是在实现处定义,也无论使用什么修饰关键字。
-
如果没有setKey:方法,也没有_key成员变量,就会搜索 _isKey成员的变量。
-
如果以上都没有,就会继续搜索Key和isKey的成员变量
-
如果方法和相应成员变量全都不存在,就会执行setValue: forUndefinedKey: 方法,默认抛出异常
简单来说:如果没有找到SetKey方法,会按照_Key, _isKey,Key,isKey的顺序搜索成员并进行赋值操作。
来尝试一下寻找_Key的成员变量
@interface KVCMethod : NSObject {NSString* _FirstName;
}
@endint main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {KVCMethod* kvcMethod = [[KVCMethod alloc] init];[kvcMethod setValue:@"李" forKey:@"FirstName"];NSLog(@"%@", [kvcMethod valueForKey:@"FirstName"]);}appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
这里将后续的代码删去了,所以只用看第一行输出的结果,可以看到运行的结果是成功找到了_key成员变量并且成功设置和取出了相应的成员变量
再将accessInstanceVariablesDirectly设置为NO运行:
我们重写处理异常的方法来检查修改accessInstanceVariablesDirectly的返回值之后程序是怎么执行的
@implementation KVCMethod
- (BOOL)validateValue:(inout id _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing _Nullable *)outError {if ([inKey isEqualToString:@"name"]) {NSString* name = (NSString*)*ioValue;if (name.length == 0) {if (outError) {*outError = [NSError errorWithDomain:@"MyDoain" code:1001 userInfo:@{NSLocalizedDescriptionKey: @"Name cannot be empty"}];}return NO;}}return YES;
}
+ (BOOL)accessInstanceVariablesDirectly {return NO;
}
- (id)valueForUndefinedKey:(NSString *)key {NSLog(@"出现异常,不存在该key:%@", key);return nil;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {NSLog(@"出现异常,不存在该key:%@", key);
}
@end
运行结果如下:
可以发现触发了处理异常的方法,也就是说程序没有按照之前的顺序寻找成员变量,也就没有成功赋值,程序输出NULL
KVC取值
当调用valueForKey: @"name"的代码时,KVC对key的都搜索方式不同于setValue: forKey: ,其搜索方式如下:
-
首先按照getKey,Key,isKey的顺序查找getter方法,找到的话会直接调用。如果是BOOL或者int等值类型,会将其包装成一个NSNumber对象
-
如果没有找到getter方法,就会查找countOf,objectIn AtIndex 或者AtIndexes 格式的方法,如果其中一个被找到,就会返回一个可以相应NSArray所有方法的代理集合(NSKeyValueArray,属于NSArray的子类),调用这个代理集合的方法或者说给它发送属于NSArray的方法,就会以countOf,objectIn Atindex或AtIndexes这几个方法组合的形式调用。
-
如果上面方法都没有找到,就会同时查照countOf,enumeratorOf,merberOf格式的方法,这三个方法都找到了的话,那么就返回一个可以相应NSSet所有方法的代理集合,和上面所说一样,给这个代理集合发送NSSet的方法,就会以countOf,enumeratorOf,merberOf组合的形式调用。
-
如果还没有找到,这时候就会检查方法accessInstanceVariablesDirectly的返回值,如果是YES,就会按照之前设值一样的顺序,搜索_Key, _isKey,Key,isKey。
KVC使用KeyPath
当自定义类的成员变量是自定义类或者其他的复杂数据类型时,可以先使用KVC获取该属性,然后再用一次KVC获得这个属性的属性。但这种方法比较繁琐,KVC有一种更简洁的方法,那就是键路径KeyPath,按照路径寻找Key
- (nullable id)valueForKeyPath:(NSString *)keyPath; //通过KeyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath; //通过KeyPath来设值
int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {KVCMethod* kvcMethod = [[KVCMethod alloc] init];SubKVCMethod* subKVCMethod = [[SubKVCMethod alloc] init];[kvcMethod setValue:subKVCMethod forKey:@"subKVCMethod"];[kvcMethod setValue:@"南崩" forKeyPath:@"subKVCMethod.name"];NSLog(@"KVCMethod的属性SubKVCMethod的属性name是%@", [kvcMethod valueForKeyPath:@"subKVCMethod.name"]);}appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
运行的结果是:
发现成功实现了赋值和取值操作,并且这里KeyPath的格式其实就类似于我们点语法的格式
KVC处理异常
之前其实已经提到过KVC处理异常的方法了,这里主要是两种异常,一种是使用了错误的Key,另一种是设值时传递了nil的值,分别可以使用两类方法来处理
KVC处理设值nil异常
KVC一般不允许在调用setValue: forKey: 时传递一个nil的值。如果传入一个nil的值,KVC会调用setNilValueForKey:方法,这个方法默认抛出异常。
#import "KVCMethod.h"
@implementation KVCMethod
- (void)setNilValueForKey:(NSString *)key {NSLog(@"不能将%@设成nil", key);
}
@end
KVC处理UndefinedKey异常
当调用setValue: forKey或者valueForKey时,一般不允许使用不存在的Key,否则会报错forUndefinedKey发生崩溃,重写forUndefinedKey可以避免崩溃
@implementation KVCMethod
- (id)valueForUndefinedKey:(NSString *)key {NSLog(@"出现异常,不存在该key:%@", key);return nil;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {NSLog(@"出现异常,不存在该key:%@", key);
}
@end
KVC处理数值和结构体类型属性
valueForKey: 方法总是会返回一个id对象,如果原本的变量类型是值类型或者结构体,返回值会封装成NSNumber或者NSValue对象,这两个类会处理数字、布尔值、指针和结构体。
在使用setValue: forKey时,必须手动将值类型转换成NSNumber或者NSValue类型,才能传递过去,因为传递进去和取出来的都是id类型,所以需要自己确保类型正确性,运行时如果类型错误会抛出异常
@interface KVCMethod : NSObject
@property(nonatomic, readwrite, assign)int age;
@end
int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {KVCMethod* kvcMethod = [[KVCMethod alloc] init];[kvcMethod setValue:[NSNumber numberWithInt:23] forKey:@"age"];NSLog(@"age = %@", [kvcMethod valueForKey:@"age"]);appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
这里就是为类添加了一个int类型的属性age,我们赋给age的是一个NSNumber对象,KVC会自动的将NSNumber对象转换成int对象,然后再调用相应的访问器方法设置age的值。
使用valueForKey:方法时,返回的值是一个NSNumber。
需要注意的是,我们不能直接将数值通过KVC赋值,需要先转换为NSNumber和NSValue类型,那么哪些类型用NSNumber封装,哪些用NSValue呢?
可以使用NSNumber的数据类型:
+ (NSNumber*)numberWithChar:(char)value;
+ (NSNumber*)numberWithUnsignedChar:(unsignedchar)value;
+ (NSNumber*)numberWithShort:(short)value;
+ (NSNumber*)numberWithUnsignedShort:(unsignedshort)value;
+ (NSNumber*)numberWithInt:(int)value;
+ (NSNumber*)numberWithUnsignedInt:(unsignedint)value;
+ (NSNumber*)numberWithLong:(long)value;
+ (NSNumber*)numberWithUnsignedLong:(unsignedlong)value;
+ (NSNumber*)numberWithLongLong:(longlong)value;
+ (NSNumber*)numberWithUnsignedLongLong:(unsignedlonglong)value;
+ (NSNumber*)numberWithFloat:(float)value;
+ (NSNumber*)numberWithDouble:(double)value;
+ (NSNumber*)numberWithBool:(BOOL)value;
+ (NSNumber*)numberWithInteger:(NSInteger)valueNS_AVAILABLE(10_5,2_0);
+ (NSNumber*)numberWithUnsignedInteger:(NSUInteger)valueNS_AVAILABLE(10_5,2_0);
可以使用NSValue的数据类型:
+ (NSValue*)valueWithCGPoint:(CGPoint)point;
+ (NSValue*)valueWithCGSize:(CGSize)size;
+ (NSValue*)valueWithCGRect:(CGRect)rect;
+ (NSValue*)valueWithCGAffineTransform:(CGAffineTransform)transform;
+ (NSValue*)valueWithUIEdgeInsets:(UIEdgeInsets)insets;
+ (NSValue*)valueWithUIOffset:(UIOffset)insetsNS_AVAILABLE_IOS(5_0);
NSValue主要用于处理结构体类型的数据,任何结构体都可以转化成NSValue对象,包括自定义的结构体
KVC键值验证
KVC有提供验证Key对应的Value是否合法的方法:
- (BOOL)validateValue:(inoutid*)ioValue forKey:(NSString*)inKey error:(outNSError**)outError;
这个方法在KVC的定义那个部分已经有过讲解,这里就不多赘述了。
KVC处理集合
简单集合运算符
简单集合运算符有@avg, @count,@max,@min,@sum5种,这五种运算符分别表示平均值,总个数,最大值,最小值和总量
int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {KVCMethod* kvcMethod1 = [[KVCMethod alloc] init];kvcMethod1.name = @"灰灰";kvcMethod1.age = 12;KVCMethod* kvcMethod2 = [[KVCMethod alloc] init];kvcMethod2.name = @"黑黑";kvcMethod2.age = 22;KVCMethod* kvcMethod3 = [[KVCMethod alloc] init];kvcMethod3.name = @"白白";kvcMethod3.age = 32;NSArray* array = [NSArray arrayWithObjects:kvcMethod1, kvcMethod2, kvcMethod3, nil];NSNumber* sum = [array valueForKeyPath:@"@sum.age"];NSLog(@"sum = %@", sum);NSNumber* avg = [array valueForKeyPath:@"@avg.age"];NSLog(@"avg = %@", avg);NSNumber* count = [array valueForKeyPath:@"@count.age"];NSLog(@"count = %@", count);NSNumber* min = [array valueForKeyPath:@"@min.age"];NSLog(@"min = %@", min);NSNumber* max = [array valueForKeyPath:@"@max.age"];NSLog(@"max = %@", max);appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
对象运算符
以数组的形式返回指定内容,有两种:
@distinctUnionOfObjects
@unionOfObjects
他们的返回值都是NSArray,区别是前者返回元素唯一,是去重后的结果,后者返回全集。
KVC处理字典
有两个关于NSDictionary的方法:
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
第一个方法是指输入一组key,返回这组key对应的属性,再组成一个字典
第二个方法是用来修改Model中对应Key的属性
@interface Address : NSObject
@property (nonatomic, copy)NSString* country;
@property (nonatomic, copy)NSString* province;
@property (nonatomic, copy)NSString* city;
@property (nonatomic, copy)NSString* district;
@end
int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {//模型转字典Address* add = [Address new];add.country = @"China";add.province = @"Guang Dong";add.city = @"Shen Zhen";add.district = @"Nan Shan";NSArray* arr = @[@"country",@"province",@"city",@"district"];NSDictionary* dict = [add dictionaryWithValuesForKeys:arr]; //把对应key所有的属性全部取出来NSLog(@"%@",dict);//字典转模型NSDictionary* modifyDict = @{@"country":@"USA",@"province":@"california",@"city":@"Los angle"};[add setValuesForKeysWithDictionary:modifyDict]; //用key Value来修改Model的属性NSLog(@"country:%@ province:%@ city:%@",add.country,add.province,add.city);
appDelegateClassName = NSStringFromClass([AppDelegate class]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
KVC应用
KVC这种基于运行时的编程方式具有很高的灵活性,因此在iOS开发中有着广泛的用途
动态地取值和设值
利用KVC动态的取值和设值是最基本的用途了。
用KVC来访问和修改私有变量
对于类里的私有属性,Objective-C是无法直接访问的,但是KVC是可以的。
Model和字典转换
这是KVC强大作用的又一次体现,KVC和Objc的runtime组合可以很容易的实现Model和字典的转换。
修改一些控件的内部属性
这也是iOS开发中必不可少的小技巧。众所周知很多UI控件都由很多内部UI控件组合而成的,但是Apple度没有提供这访问这些控件的API,这样我们就无法正常地访问和修改这些控件的样式。 而KVC在大多数情况可下可以解决这个问题。最常用的就是个性化UITextField中的placeHolderText了。
操作集合
Apple对KVC的valueForKey:方法作了一些特殊的实现,比如说NSArray和NSSet这样的容器类就实现了这些方法。所以可以用KVC很方便地操作集合。
用KVC实现高阶消息传递
当对容器类使用KVC时,valueForKey:将会被传递给容器中的每一个对象,而不是容器本身进行操作。结果会被添加进返回的容器中,这样,开发者可以很方便的操作集合来返回另一个集合。
实现KVO
KVO是基于KVC实现的,下面讲一下KVO的概念和实现。
相关文章:

【iOS】KVC
文章目录 KVC的定义 容器类中KVC的实现 KVC设值 KVC取值 KVC使用KeyPath KVC处理异常 KVC处理设值nil异常 KVC处理UndefinedKey异常 KVC处理数值和结构体类型属性 KVC键值验证 KVC处理集合 简单集合运算符 对象运算符 KVC处理字典 KVC应用 动态地取值和设值 用…...

【2024年华为杯研究生数学建模竞赛C题】完整论文与代码
这里写目录标题 基于数据驱动下磁性元件的磁芯损耗建模一、问题重述1.1问题背景1.2问题回顾 问题分析与模型假设模型建立与求解 基于数据驱动下磁性元件的磁芯损耗建模 一、问题重述 1.1问题背景 在现代电力电子和变压器设计中,磁性元件是确保能量高效传递和系统稳…...

svn回退到以前历史版本修改并上传
svn回退到以前版本,并在以前版本上修改代码后,上传到svn库当中,如下步骤: 3、 以回退到版本号4为例:选中版本号4,右键->Revert to this version,在出现的对话框中 点击yes! 4、 5、...

fiddler抓包07_抓IOS手机请求
课程大纲 前提:电脑和手机连接同一个局域网 (土小帽电脑和手机都连了自己的无线网“tuxiaomao”。) 原理如下: 电脑浏览器抓包时,直接就是本机网络。手机想被电脑Fiddler抓包,就要把Fiddler变成手机和网络…...

Windows系统及Ubuntu系统安装Java
Java语言简介 Java是一种高级编程语言,Java语言的创始可以追溯到1990年代初,当时任职于Sun Microsystems(后来被甲骨文公司收购)的詹姆斯高斯林(James Gosling)等人开始开发一种名为“Oak”(名字来源于詹姆…...

uni-data-select 使用 localdata 传入数据出现 不回显 | 下拉显示错误的 解决方法
目录 1. 问题所示2. 正确Demo3. 下拉显示错误(Bug复现)4. 下拉不回显(Bug复现)1. 问题所示 uni-app的下拉框uni-data-select 使用 localdata 传入数据 主要总结正确的Demo以及复现一些Bug 数据不回显数据不显示下拉选项2. 正确Demo 详细的基本知识推荐阅读:uni-app中的…...

图解 TCP 四次挥手|深度解析|为什么是四次|为什么要等2MSL
写在前面 今天我们来图解一下TCP的四次挥手、深度解析为什么是四次? 上一片文章我们已经介绍了TCP的三次握手 解析四次挥手 数据传输完毕之后,通信的双方都可释放连接。现在客户端A和服务端B都处于ESTABLISHED状态。 第一次挥手 客户端A的应用进…...

DevExpress中文教程:如何将WinForms数据网格连接到ASP. NET Core WebAPI服务?
日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData),在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。 P.S:DevExpress WinForms拥有180…...

SpringBoot3核心特性-核心原理
目录 传送门前言一、事件和监听器1、生命周期监听2、事件触发时机 二、自动配置原理1、入门理解1.1、自动配置流程1.2、SPI机制1.3、功能开关 2、进阶理解2.1、 SpringBootApplication2.2、 完整启动加载流程 三、自定义starter1、业务代码2、基本抽取3、使用EnableXxx机制4、完…...

Linux:RPM软件包管理以及yum软件包仓库
挂载光驱设备 RPM软件包管理 RPM软件包简介 区分软件名和软件包名 软件名:firefox 软件包名:firefox-52.7.0-1.el7.centos.x86_64.rpm 查询软件信息 查询软件(参数为软件名) ]# rpm -qa #当前系统中所有已安装的软件包 ]# r…...

pod介绍与配置
1、pod概念介绍 Pod 是 kubernetes 基本调度单位。每个 Pod 中可以运 行一个或多个容器,共享 Pod 的文件系统、IP 和网络等资源,每个 Pod 只有一个 IP。 2、使用 yaml或json 文件创建 Pod 声明式文件方式创建 Pod,支持 yaml 和 json 1&…...

【Taro】初识 Taro
笔记来源:编程导航。 概述 Taro 官方文档:https://taro-docs.jd.com/docs/ (跨端开发框架) Taro 官方框架兼容的组件库: taro-ui:https://taro-ui.jd.com/#/ (最推荐,兼容性最好&…...

【设计模式-备忘录】
备忘录模式(Memento Pattern)是一种行为型设计模式,用于保存对象的内部状态,以便在将来某个时间可以恢复到该状态,而不暴露对象的内部实现细节。备忘录模式特别适合在需要支持撤销(Undo)操作的应…...

【数据结构】排序算法系列——快速排序(附源码+图解)
快速排序 接下来我们将要介绍的是排序中最为重要的算法之一——快速排序。 快速排序(英语:Quicksort),又称分区交换排序(partition-exchange sort),最早由东尼霍尔提出。快速排序通常明显比其…...

Arthas thread(查看当前JVM的线程堆栈信息)
文章目录 二、命令列表2.1 jvm相关命令2.1.2 thread(查看当前JVM的线程堆栈信息)举例1:展示[数字]线程的运行堆栈,命令:thread 线程ID举例2:找出当前阻塞其他线程的线程 二、命令列表 2.1 jvm相关命令 2.…...

Tomcat_WebApp
Tomcat的目录的介绍 /bin: 这个目录包含启动和关闭 Tomcat 的脚本。 startup.bat / startup.sh:用于启动 Tomcat(.bat 文件是 Windows 系统用的,.sh 文件是 Linux/Unix 系统用的)。shutdown.bat / shutdown.sh…...

代码随想录算法训练营Day10
150. 逆波兰表达式求值 力扣题目链接;. - 力扣(LeetCode) Collection——Deque——LInkedList类 class Solution {public int evalRPN(String[] tokens) {Deque<Integer> myquenew LinkedList<>();for(String a:tokens){if(a.…...

十个服务器中毒的常见特征及其检测方法
服务器作为企业的核心资源,其安全性至关重要。一旦服务器被病毒入侵,不仅会影响系统的正常运行,还可能导致数据泄露等严重后果。以下是十种常见的服务器中毒特征及其检测方法。 1. 系统性能下降 病毒常常占用大量的CPU和内存资源࿰…...

LeetCode 每周算法 6(图论、回溯)
LeetCode 每周算法 6(图论、回溯) 图论算法: class Solution: def dfs(self, grid: List[List[str]], r: int, c: int) -> None: """ 深度优先搜索函数,用于遍历并标记与当前位置(r, c)相连的所有陆地&…...

Selenium元素定位:深入探索与实践
目录 一、引言 二、Selenium元素定位基础 1. WebDriver与元素定位 2. 定位策略概览 三、ID定位 1. 特点与优势 2. 示例代码 四、Class Name定位 1. 特点与限制 2. 示例代码 五、XPath定位 1. 特点与优势 2. 示例代码 3. XPath高级用法 六、CSS Selector定位 1.…...

前端开发——(1)使用vercel进行网页开发
前端开发——(1)使用Vercel进行网页开发 在现代前端开发中,选择一个高效的部署平台至关重要。Vercel 提供了快速、简便的部署方式,特别适合静态网站和 Next.js 应用。本文将带你逐步了解如何使用 Vercel 部署并运行你的网页项目。…...

故障诊断│GWO-DBN灰狼算法优化深度置信网络故障诊断
1.引言 随着人工智能技术的快速发展,深度学习已经成为解决复杂问题的热门方法之一。深度置信网络(DBN)作为深度学习中应用比较广泛的一种算法,被广泛应用于分类和回归预测等问题中。然而,DBN的训练过程通常需要大量的…...

【工具】Windows|两款开源桌面窗口管理小工具Deskpins和WindowTop
总结 Deskpins 功能单一,拖到窗口上窗口就可以置顶并且标记钉子标签,大小 104 KB,开源位置:https://github.com/thewhitegrizzli/DeskPins/releases WindowTop 功能完善全面强大,包括透明度、置顶、选区置顶等一系列功…...

【Unity杂谈】iOS 18中文字体显示问题的调查
一、问题现象 最近苹果iOS 18系统正式版推送,周围升级系统的同事越来越多,有些同事发现,iOS 18上很多游戏(尤其是海外游戏)的中文版,显示的字很奇怪,就像一些字被“吞掉了”,无法显示…...

后端-navicat查找语句(单表与多表)
表格字段设置如图 语句: 1.输出 1.输出name和age列 SELECT name,age from student 1.2.全部输出 select * from student 2.where子语句 1.运算符: 等于 >大于 >大于等于 <小于 <小于等于 ! <>不等于 select * from stude…...

基于springboot的在线视频点播系统
文未可获取一份本项目的java源码和数据库参考。 国外研究现状: 与传统媒体不同的是,新媒体在理念和应用上都采用了新颖的媒介或媒体。新媒体是指应用在数字技术、在传统媒体基础上改造、或者更新换代而来的媒介或媒体。新兴媒体与传统媒体在理念和应用…...

笔记整理—内核!启动!—kernel部分(8)动态编译链接库与BSP文件
linux的C语言程序是用编译的,但是如果要在开发板上运行的话就不能使用默认的ubuntu提供的gcc编译器,而是使用arm-linux版本的一类的编译器。我们可以用file xx去查看一个程序的架构。 (arm架构) (intel的80386架构&…...

Cpp类和对象(中续)(5)
文章目录 前言一、赋值运算符重载运算符重载赋值运算符重载赋值运算符不可重载为全局函数前置和后置的重载 二、const修饰成员函数三、取地址及const取地址操作符重载四、日期类的实现构造函数日期 天数日期 天数日期 - 天数日期 - 天数日期类的大小比较日期类 > 日期类日…...

深度学习02-pytorch-01-张量的创建
深度学习 pytorch 框架 是目前最热门的。 深度学习 pytorch 框架相当于 机器学习阶段的 numpy sklearn 它将数据封装成张量(Tensor)来进行处理,其实就是数组。也就是numpy 里面的 ndarray . pip install torch1.10.0 -i https://pypi.tuna.tsinghua.edu.cn/simp…...

pg入门9—pg中的extentions是什么
在 PostgreSQL(PG)中,Extension(扩展) 是一组预先打包的功能模块,可以轻松地添加到数据库中以扩展其功能。这些扩展通常包含新的数据类型、函数、索引方法、操作符以及其他数据库增强功能。通过扩展&#x…...