当前位置: 首页 > news >正文

【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问题背景 在现代电力电子和变压器设计中&#xff0c;磁性元件是确保能量高效传递和系统稳…...

svn回退到以前历史版本修改并上传

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

fiddler抓包07_抓IOS手机请求

课程大纲 前提&#xff1a;电脑和手机连接同一个局域网 &#xff08;土小帽电脑和手机都连了自己的无线网“tuxiaomao”。&#xff09; 原理如下&#xff1a; 电脑浏览器抓包时&#xff0c;直接就是本机网络。手机想被电脑Fiddler抓包&#xff0c;就要把Fiddler变成手机和网络…...

Windows系统及Ubuntu系统安装Java

Java语言简介 Java是一种高级编程语言&#xff0c;Java语言的创始可以追溯到1990年代初&#xff0c;当时任职于Sun Microsystems&#xff08;后来被甲骨文公司收购&#xff09;的詹姆斯高斯林&#xff08;James Gosling&#xff09;等人开始开发一种名为“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的四次挥手、深度解析为什么是四次&#xff1f; 上一片文章我们已经介绍了TCP的三次握手 解析四次挥手 数据传输完毕之后&#xff0c;通信的双方都可释放连接。现在客户端A和服务端B都处于ESTABLISHED状态。 第一次挥手 客户端A的应用进…...

DevExpress中文教程:如何将WinForms数据网格连接到ASP. NET Core WebAPI服务?

日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData)&#xff0c;在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。 P.S&#xff1a;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软件包简介 区分软件名和软件包名 软件名&#xff1a;firefox 软件包名&#xff1a;firefox-52.7.0-1.el7.centos.x86_64.rpm 查询软件信息 查询软件&#xff08;参数为软件名&#xff09; ]# rpm -qa #当前系统中所有已安装的软件包 ]# r…...

pod介绍与配置

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

【Taro】初识 Taro

笔记来源&#xff1a;编程导航。 概述 Taro 官方文档&#xff1a;https://taro-docs.jd.com/docs/ &#xff08;跨端开发框架&#xff09; Taro 官方框架兼容的组件库&#xff1a; taro-ui&#xff1a;https://taro-ui.jd.com/#/ &#xff08;最推荐&#xff0c;兼容性最好&…...

【设计模式-备忘录】

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

【数据结构】排序算法系列——快速排序(附源码+图解)

快速排序 接下来我们将要介绍的是排序中最为重要的算法之一——快速排序。 快速排序&#xff08;英语&#xff1a;Quicksort&#xff09;&#xff0c;又称分区交换排序&#xff08;partition-exchange sort&#xff09;&#xff0c;最早由东尼霍尔提出。快速排序通常明显比其…...

Arthas thread(查看当前JVM的线程堆栈信息)

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

Tomcat_WebApp

Tomcat的目录的介绍 /bin&#xff1a; 这个目录包含启动和关闭 Tomcat 的脚本。 startup.bat / startup.sh&#xff1a;用于启动 Tomcat&#xff08;.bat 文件是 Windows 系统用的&#xff0c;.sh 文件是 Linux/Unix 系统用的&#xff09;。shutdown.bat / shutdown.sh&#xf…...

代码随想录算法训练营Day10

150. 逆波兰表达式求值 力扣题目链接&#xff1b;. - 力扣&#xff08;LeetCode&#xff09; Collection——Deque——LInkedList类 class Solution {public int evalRPN(String[] tokens) {Deque<Integer> myquenew LinkedList<>();for(String a:tokens){if(a.…...

十个服务器中毒的常见特征及其检测方法

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

LeetCode 每周算法 6(图论、回溯)

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

Selenium元素定位:深入探索与实践

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

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...