认识CoreData-基础使用

2023-05-16

 

 

第一篇文章中并没有讲CoreData的具体用法,只是对CoreData做了一个详细的介绍,算是一个开始和总结吧。 这篇文章中会主要讲CoreData的基础使用,以及在使用中需要注意的一些细节。因为文章中会插入代码和图片,内容可能会比较多,比较考验各位耐心。

 

文章中如有疏漏或错误,还请各位及时提出,谢谢!?

 


 

创建自带CoreData的工程

 

在新建一个项目时,可以勾选Use Core Data选项,这样创建出来的工程系统会默认生成一些CoreData的代码以及一个.xcdatamodeld后缀的模型文件,模型文件默认以工程名开头。这些代码在AppDelegate类中,也就是代表可以在全局使用AppDelegate.h文件中声明的CoreData方法和属性。

 

系统默认生成的代码是非常简单的,只是生成了基础的托管对象模型、托管对象上下文、持久化存储调度器,以及MOC的save方法。但是这些代码已经可以完成基础的CoreData操作了。

 

 

系统生成代码

这部分代码不应该放在AppDelegate中,尤其对于大型项目来说,更应该把这部分代码单独抽离出去,放在专门的类或模块来管理CoreData相关的逻辑。所以我一般不会通过这种方式创建CoreData,我一般都是新建一个“干净”的项目,然后自己往里面添加,这样对于CoreData的完整使用流程掌握的也比较牢固。

 


 

CoreData模型文件的创建

 

构建模型文件

 

使用CoreData的第一步是创建后缀为.xcdatamodeld的模型文件,使用快捷键Command + N,选择Core Data -> Data Model -> Next,完成模型文件的创建。

创建完成后可以看到模型文件左侧列表,有三个选项Entities、Fetch Requests、Configurations,分别对应着实体、请求模板、配置信息。

 

 

添加实体

 

现在可以通过长按左侧列表下方的Add Entity按钮,会弹出Add Entity、Add Fetch Request、Add Configuration选项,可以添加实体、请求模板、配置信息。这里先选择Add Entity来添加一个实体,命名为Person。

 

添加Person实体后,会发现一个实体对应着三部分内容,Attributes、Relationships、Fetched Properties,分别对应着属性、关联关系、获取操作。

 

 

空实体

 

现在对Person实体添加两个属性,添加age属性并设置type为Integer 16,添加name属性并设置type为String。

 

 

添加属性

 

实体属性类型

 

在模型文件的实体中,参数类型和平时创建继承自NSObject的模型类大体类似,但是还是有一些关于类型的说明,下面简单的列举了一下。

 

  • Undefined: 默认值,参与编译会报错

  • Integer 16: 整数,表示范围 -32768 ~ 32767

  • Integer 32: 整数,表示范围 -2147483648 ~ 2147483647

  • Integer 64: 整数,表示范围 –9223372036854775808 ~ 9223372036854775807

  • Float: 小数,通过MAXFLOAT宏定义来看,最大值用科学技术法表示是 0x1.fffffep+127f

  • Double: 小数,小数位比Float更精确,表示范围更大

  • String: 字符串,用NSString表示

  • Boolean: 布尔值,用NSNumber表示

  • Date: 时间,用NSDate表示

  • Binary Data: 二进制,用NSData表示

  • Transformable: OC对象,用id表示。可以在创建托管对象类文件后,手动改为对应的OC类名。使用的前提是,这个OC对象必须遵守并实现NSCoding协议

 

添加实体关联关系

 

创建两个实体Department和Employee,并且在这两个实体中分别添加一些属性,下面将会根据这两个实体来添加关联关系。

 

 

创建实体

 

给Employee实体添加关系,在Relationships的位置点击加号,添加一个关联关系。添加关系的名称设为department,类型设置为Department,Inverse设置为employee(后面会讲解这个inverse的作用)。

 

 

添加Relationships

 

选择Department实体,点击Relationships位置的加号,添加关联关系。

Department实体添加Relationships的操作和Employee都一样,区别在于用红圈标出的Type,这里设置的To Many一对多的关系。这里默认是To One一对一,上面的Employee就是一对一的关系。也就符合一个Department可以有多个Employee,而Employee只能有一个Department的情况,这也是符合常理的。

 

 

添加Relationships

 

Relationships类似于SQLite的外键,定义了在同一个模型中,实体与实体之间的关系。可以定义为对一关系或对多关系,也可以定义单向或双向的关系,根据需求来确定。如果是对多的关系,默认是使用NSSet集合来存储模型。

 

Inverse是两个实体在Relationships中设置关联关系后,通过设置inverse为对应的实体,这样可以从一个实体找到另一个实体,使两个实体具有双向的关联关系。

 

Fetched Properties

 

在实体最下面,有一个Fetched Properties选项,这个选项用的不多,这里就不细讲了。

 

Fetched Properties用于定义查询操作,和NSFetchRequest功能相同。定义fetchedProperty对象后,可以通过NSManagedObjectModel类的fetchRequestFromTemplateWithName:substitutionVariables:方法或其他相关方法获取这个fetchedProperty对象。

 

 

获取这个对象后,系统会默认将这个对象缓存到一个字典中,缓存之后也可以通过fetchedProperty字典获取fetchedProperty对象。

 

Data Model Inspector

 

选中一个实体后,右侧的侧边栏(Data Model Inspector)还有很多选项,这些选项可以对属性进行配置。根据不同的属性类型,侧边栏的显示也不太一样,下面是一个String类型的属性。

 

Data Model Inspector

 

属性设置

 

  • default Value: 设置默认值,除了二进制不能设置,其他类型几乎都能设置。

  • optional: 在使用时是否可选,也可以理解为如果设置为NO,只要向MOC进行save操作,这个属性是否必须有值。否则MOC进行操作时会失败并返回一个error,该选项默认为YES。

  • transient: 设置当前属性是否只存在于内存,不被持久化到本地,如果设置为YES,这个属性就不参与持久化操作,属性的其他操作没有区别。transient非常适合存储一些在内存中缓存的数据,例如存储临时数据,这些数据每次都是不同的,而且不需要进行本地持久化,所以可以声明为transient的属性。

  • indexed: 设置当前属性是否是索引。添加索引后可以有效的提升检索操作的速度。但是对于删除这样的操作,删除索引后其他地方还需要做出相应的变化,所以速度会比较慢。

  • Validation: 通过Validation可以设置Max Value和Min Value,通过这两个条件来约定数据,对数据的存储进行一个验证。数值类型都有相同的约定方式,而字符串则是约定长度,date是约定时间。

  • Reg. Ex.(Regular Expression): 可以设置正则表达式,用来验证和控制数据,不对数据自身产生影响。(只能应用于String类型)

  • Allows External Storage: 当存储二进制文件时,如果遇到比较大的文件,是否存储在存储区之外。如果选择YES,存储文件大小超过1MB的文件,都会存储在存储区之外。否则大型文件存储在存储区内,会造成SQLite进行表操作时,效率受到影响。

 

Relationships设置

 

  • delete rule: 定义关联属性的删除规则。在当前对象和其他对象有关联关系时,当前对象被删除后与之关联对象的反应。这个参数有四个枚举值,代码对应着模型文件的相同选项。

  • NSNoActionDeleteRule 删除后没有任何操作,也不会将关联对象的关联属性指向nil。删除后使用关联对象的关联属性,可能会导致其他问题。

  • NSNullifyDeleteRule 删除后会将关联对象的关联属性指向nil,这是默认值。

  • NSCascadeDeleteRule 删除当前对象后,会将与之关联的对象也一并删除。

  • NSDenyDeleteRule 在删除当前对象时,如果当前对象还指向其他关联对象,则当前对象不能被删除。

  • Type: 主要有两种类型,To One和To Many,表示当前关系是一对多还是一对一。

 

实体

 

  • Parent Entity: 可以在实体中创建继承关系,在一个实体的菜单栏中通过Parent Entity可以设置父实体,这样就存在了实体的继承关系,最后创建出来的托管模型类也是具有继承关系的。注意继承关系中属性名不要相同。

 

使用了这样的继承关系后,系统会将子类继承父类的数据,存在父类的表中,所有继承自同一父类的子类都会将父类部分存放在父类的表中。这样可能会导致父类的表中数据量过多,造成性能问题。

 

Fetch Requests

 

在模型文件中Entities下面有一个Fetch Requests,这个也是配置请求对象的。但是这个使用起来更加直观,可以很容易的完成一些简单的请求配置。相对于上面讲到的Fetched Properties,这个还是更方便使用一些。

 

 

上面是对Employee实体的height属性配置的Fetch Request,这里配置的height要小于2米。配置之后可以通过NSManagedObjectModel类的fetchRequestTemplateForName:方法获取这个请求对象,参数是这个请求配置的名称,也就是EmployeeFR。

 

Editor Style

 

这是我认为CoreData最大的优势之一,可视化的模型文件结构。可以很清楚的看到实体和属性的关系,以及实体之间的对应关系。

 

 

Editor Style

 

一个.xcdatamodeld模型文件的展示风格有两种,一种是列表的形式(Table),另一种是图表的形式展示(Graph)。

 

图表看起来更加直观,而图表在操作上也有一些比Table更方便的地方。例如在Table的状态下添加两个实体的关联关系,如果只做一次关联操作,默认是单向的关系。而在Graph的状态下,按住Control对两个图表进行连线,两个实体的结果就是双向关联的关系。

 

手动创建实体

 

假设不使用.xcdatamodeld模型文件,全都是纯代码,怎么在项目里创建实体啊?这样的话就需要通过代码创建实体描述、关联描述等信息,然后设置给NSManagedObjectModel对象。而使用模型文件的话一般都是通过NSManagedObjectModel对象来读取文件。

 

如果是纯代码的话,苹果更推荐使用KVC的方式存取值,然后所有托管对象都用NSManagedObject创建。但是这样存在的问题很多,开发成本比较大、使用不方便等等。最大的问题就是写属性名的key字符串,很容易出错,而且这样失去了CoreData原有的优点。所以还是推荐使用.xcdatamodeld模型文件的开发方式。

 

创建托管对象类文件

 

创建文件

 

创建实体后,就可以根据对应的实体,生成开发中使用的基于NSManagedObject类的托管对象类文件。

还是按照上面Department和Employee的例子,先创建一个Department实体。因为Department实体有对多关系,生成托管对象类文件的关联属性不一样,可以体现出和对一关系的区别,所以使用Department实体生成文件。

 

快捷键Command + N -> NSManagedObject subclass -> 选择模型文件 -> 选择实体,生成Department实体对应的托管对象类文件。

 

 

生成的托管对象类文件

 

可以看到上面生成了四个文件,以实体名开头的.h和.m文件,另外两个是这个实体的Category文件。为什么生成Category文件?一会再说,先打开类文件进去看看。

 

Category

 

 

实体Category

 

可以看到类文件中有两个Category,分别是CoreDataProperties和CoreDataGeneratedAccessors。其中如果没有设置对多关系的实体,只会有CoreDataProperties,而设置了对多关系的实体系统会为其生成CoreDataGeneratedAccessors。

 

CoreDataProperties中会生成实体中声明的Attributes和Relationships中的属性,其中对多关系是用NSSet存储的属性,如果是对一的关系则是非集合的对象类型属性。再看.m文件中,所有属性都用@dynamic修饰,CoreData会在运行时动态为所有Category中的属性生成实现代码,所以这里用@dynamic修饰。

 

对多属性生成的CoreDataGeneratedAccessors,是系统自动生成管理对多属性集合的方法,一般都是一个属性对应四个方法,方法的实现也是在运行时动态实现的,方法都是用来操作集合对象的。

 

托管对象类文件

 

点击系统生成的托管对象类文件,此类是继承自NSManagedObject类的。可以看到里面非常干净,没有其他逻辑代码。

 

根据苹果的注释代码:Insert code here to declare functionality of your managed object subclass,提示应该在这个文件中编写此类相关的逻辑代码。这里就是编写此类逻辑代码的地方,当然也可以什么都不写,看需求啦。

 

任意类型属性

 

实体支持创建任意继承自NSObject类的属性,例如项目中手动创建的类。项目中创建的类在下拉列表中并不会体现,可以在属性类型选择transformable类型,然后生成托管对象类文件的时候,系统会将这个属性声明为id类型,在创建类文件后,可以直接手动更改这个属性的类型为我们想要的类型。

 

对于手动设置的属性有一个要求,属性所属的类必须是遵守NSCoding协议,因为这个属性要被归档到本地。

 

标量类型

 

创建托管对象类文件时,实体属性的类型无论是选择的integer32还是float,只要是基础数据类型,最后创建出来的默认都是NSNumber类型的,这是Xcode默认的。

 

如果需要生成的属性类型是基础数据类型,可以在创建文件时勾选Use scalar properties for primitive data types选项,这样就告诉系统需要生成标量类型属性,创建出来的属性就是int64_t、float这样的基础数据类型。

 

 

标量类型

 

更新文件

 

当前模型对应的实体发生改变后,需要重新生成模型Category文件。生成步骤和上面一样,主要是替换Category文件,托管对象文件不会被替换。生成文件时不需要删除,直接替换文件。

 


 

CoreData增删改查

 

下面关于CoreData的相关操作,还是基于上面Department和Employee的例子。并且引入了Company当做.xcdatamodeld模型文件,前面两个实体被包含在Company中。

 

先讲讲NSManagedObjectContext

 

在iOS5之前创建NSManagedObjectContext对象时,都是直接通过init方法来创建。iOS5之后苹果更加推荐使用initWithConcurrencyType:方法来创建,在创建的时候指定当前是什么类型的并发队列,初始化方法参数是一个枚举值。这里简单说说MOC,后面多线程部分还会涉及MOC多线程相关的东西。

 

NSManagedObjectContext初始化方法的枚举值参数主要有三个类型:

 

  • NSConfinementConcurrencyType 如果使用init方法初始化上下文,默认就是这个并发类型。在iOS9之后已经被苹果废弃,不建议用这个API,调用某些比较新的CoreData的API可能会导致崩溃。

  • NSPrivateQueueConcurrencyType 私有并发队列类型,操作都是在子线程中完成的。

  • NSMainQueueConcurrencyType 主并发队列类型,如果涉及到UI相关的操作,应该考虑使用这个参数初始化上下文。

 

如果还使用init方法,可能会对后面推出的一些API不兼容,导致多线程相关的错误。例如下面的错误,因为如果没有显式的设置并发类型,默认是一个已经弃用的NSConfinementConcurrencyType类型,就会导致新推出的API发生不兼容的崩溃错误。

 

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSConfinementConcurrencyType context

 

创建MOC

 

下面是根据Company模型文件,创建了一个主队列并发类型的MOC。

 

// 创建上下文对象,并发队列设置为主队列

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

 

// 创建托管对象模型,并使用Company.momd路径当做初始化参数

NSURL *modelPath = [[NSBundle mainBundle] URLForResource:@"Company" withExtension:@"momd"];

NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelPath];

 

// 创建持久化存储调度器

NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

 

// 创建并关联SQLite数据库文件,如果已经存在则不会重复创建

NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;

dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite", @"Company"];

[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:nil];

 

// 上下文对象设置属性为持久化存储器

context.persistentStoreCoordinator = coordinator;

 

这段代码创建了一个MOC,我们从上往下看这段代码。

 

momd文件

 

关于MOC的并发队列类型上面已经简单说了,MOC下面出现了momd的字样,这是什么东西?

 

 

momd文件

 

在创建后缀为.xcdatamodeld的模型文件后,模型文件在编译期将会被编译为后缀为.momd的文件,存放在.app中,也就是Main Bundle中。在存在多个模型文件时,我们需要通过加载不同的.momd文件,来创建不同的NSManagedObjectModel对象,每个NSManagedObjectModel对应着不同的模型文件。

 

NSManagedObjectModel类中包含了模型文件中的所有entities、configurations、fetchRequests的描述。虽然.momd文件是支持存放在.app中的,其他人可以通过打开.app包看到这个文件。但是这个文件是经过编码的,并不会知道这个.momd文件中的内容,所以这个文件是非常安全的。通过NSManagedObjectModel获取模型文件描述后,来创建和关联数据库,并交给PSC管理。

 

如果不指定NSManagedObjectModel对应哪个模型文件,直接使用init方法初始化NSManagedObjectModel类,系统会默认将所有模型文件的表都放在一个SQLite数据库中。所以需要使用mainBundle中的不同.momd文件,对不同的NSManagedObjectModel进行初始化,这样在创建数据库时就会创建不同的数据库文件。

 

持久化存储调度器(PSC)

 

在NSManagedObjectModel下面就是NSPersistentStoreCoordinator,这个类在CoreData框架体系中起到了“中枢”的作用。对上层起到了提供简单的调用接口,并向上层隐藏持久化实现逻辑。对下层起到了协调多个持久化存储对象(NSPersistentStore),使下层只需要专注持久化相关逻辑。

 

 

持久化存储调度器

 

addPersistentStoreWithType: configuration: URL: options: error:方法是PSC创建并关联数据库的部分,关联本地数据库后会返回一个NSPersistentStore类型对象,这个对象负责具体持久化存储的实现。可以看到这个方法是一个实例方法,也就是可以添加多个持久化存储对象,并且多个持久化存储对象都关联一个PSC,这是允许的,在上面的图中也看到了这样的结构。但是这样的需求并不多,而且管理起来比较麻烦,一般都不会这样做。

 

PSC有四种可选的持久化存储方案,用得最多的是SQLite的方式。其中Binary和XML这两种方式,在进行数据操作时,需要将整个文件加载到内存中,这样对内存的消耗是很大的。

 

  • NSSQLiteStoreType : SQLite数据库

  • NSXMLStoreType : XML文件

  • NSBinaryStoreType : 二进制文件

  • NSInMemoryStoreType : 直接存储在内存中

 

插入操作

 

// 创建托管对象,并指明创建的托管对象所属实体名

Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:context];

emp.name = @"lxz";

emp.height = @1.7;

emp.brithday = [NSDate date];

 

// 通过上下文保存对象,并在保存前判断是否有更改

NSError *error = nil;

if (context.hasChanges) {

    [context save:&error];

}

 

// 错误处理

if (error) {

    NSLog(@"CoreData Insert Data Error : %@", error);

}

 

通过NSEntityDescription的insert类方法,生成并返回一个Employee托管对象,并将这个对象插入到指定的上下文中。

MOC将操作的数据存放在缓存层,只有调用MOC的save方法后,才会真正对数据库进行操作,否则这个对象只是存在内存中,这样做避免了频繁的数据库访问。

 

删除操作

 

// 建立获取数据的请求对象,指明对Employee实体进行删除操作

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];

 

// 创建谓词对象,过滤出符合要求的对象,也就是要删除的对象

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@", @"lxz"];

request.predicate = predicate;

 

// 执行获取操作,找到要删除的对象

NSError *error = nil;

NSArray *employees = [context executeFetchRequest:request error:&error];

 

// 遍历符合删除要求的对象数组,执行删除操作

[employees enumerateObjectsUsingBlock:^(Employee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

    [context deleteObject:obj];

}];

 

// 保存上下文

if (context.hasChanges) {

    [context save:nil];

}

 

// 错误处理

if (error) {

    NSLog(@"CoreData Delete Data Error : %@", error);

}

 

首先获取需要删除的托管对象,遍历获取的对象数组,逐个删除后调用MOC的save方法保存。

 

修改操作

 

// 建立获取数据的请求对象,并指明操作的实体为Employee

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];

 

// 创建谓词对象,设置过滤条件

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@", @"lxz"];

request.predicate = predicate;

 

// 执行获取请求,获取到符合要求的托管对象

NSError *error = nil;

NSArray *employees = [context executeFetchRequest:request error:&error];

[employees enumerateObjectsUsingBlock:^(Employee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

    obj.height = @3.f;

}];

 

// 将上面的修改进行存储

if (context.hasChanges) {

    [context save:nil];

}

 

// 错误处理

if (error) {

    NSLog(@"CoreData Update Data Error : %@", error);

}

 

和上面一样,首先获取到需要更改的托管对象,更改完成后调用MOC的save方法持久化到本地。

 

查找操作

 

// 建立获取数据的请求对象,指明操作的实体为Employee

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];

 

// 执行获取操作,获取所有Employee托管对象

NSError *error = nil;

NSArray *employees = [context executeFetchRequest:request error:&error];

[employees enumerateObjectsUsingBlock:^(Employee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

    NSLog(@"Employee Name : %<a href="http://www.jobbole.com/members/uz441800">@,</a> Height : %<a href="http://www.jobbole.com/members/uz441800">@,</a> Brithday : %@", obj.name, obj.height, obj.brithday);

}];

 

// 错误处理

if (error) {

    NSLog(@"CoreData Ergodic Data Error : %@", error);

}

 

查找操作最简单粗暴,因为是演示代码,所以直接将所有Employee表中的托管对象加载出来。在实际开发中肯定不会这样做,只需要加载需要的数据。后面还会讲到一些更高级的操作,会涉及到获取方面的东西。

 

总结

 

在CoreData中所有的托管对象被创建出来后,都是关联着MOC对象的。所以在对象进行任何操作后,都会被记录在MOC中。在最后调用MOC的save方法后,MOC会将操作交给PSC去处理,PSC将会将这个存储任务指派给NSPersistentStore对象。

 

上面的增删改查操作,看上去大体流程都差不多,都是一些最基础的简单操作,在下一篇文章中将会将一些比较复杂的操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

认识CoreData-基础使用 的相关文章

  • 如何使用linux程序mdadm创建软件RAID1软阵列

    如何使用linux程序mdadm创建软件RAID1软阵列 磁盘冗余阵列 RAID 是将多个物理磁盘结合成一个逻辑磁盘的技术 xff0c 该技术可以提高磁盘容错性能 xff0c 提高磁盘的读写速度 根据数据存储的排列 如 xff1a 条带存储
  • 极乐净土----Android实现图片转ascii码字符图的一些尝试

    掘金第一篇 xff0c 先转一个自己以前的帖子吧 xff0c 懒得重新写了 www jianshu com p 357af674a 转载于 https juejin im post 5c36df2cf265da616624abc6
  • idea中使用FindBugs-IDEA插件

    下载 安装 重启idea即可 xff1b 项目右键或者文件右键即可看到 FindBugs 选项 选择某个选项直接检测即可 检测结果如下图 xff1a 这里的Correctness是重点关注对象 这里面的错误往往是比较严重的 像空指针之类的错
  • pip,virtualenv,conda和anaconda的个人理解

    1 pip pip是python下的包管理工具 xff0c 主要用于从pypi下载所需的python包 xff0c 但是pip不会自动处理包之间的依赖关系 xff1b 在使用pip安装包时 xff0c 可以修改安装源为https pypi
  • Windows Server 2016-Hyper-V网络虚拟化概述

    在 Windows Server 2016 和虚拟机管理器中 xff0c Microsoft 提供的端到端网络虚拟化解决方案 有构成了 Microsoft 的网络虚拟化解决方案的五个主要组件 xff1a Windows Azure Wind
  • mac环境下安装pysvn

    可以从下载页下载对应版本的pysvn xff1a https pysvn sourceforge io downloads html 之后双击打开安装即可 xff0c 不需要再用pip安装 需要注意的是 xff0c 如果安装时提示chdir
  • 关于PHP中Session文件过多的问题

    PHP的默认机制 xff1a 每一次php请求 xff0c 会有1 100的概率 xff08 默认值 xff09 触发 session回收 如果 session回收 发生 xff0c 那就会检查 tmp sess 的文件 xff0c 如果最
  • RDO 远程 桌面无法复制

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 这里是列表文本这里是列表文本首先我们要检查 登录机在进程管理器中是否有rdpclipe exe这个进程 如果有则杀掉 xff0c 如果没有 xff0c 则在任务管理器中菜单
  • 如何在 Excel 中自定义菜单和菜单栏

    Microsoft 提供的编程示例只用于说明目的 xff0c 不附带任何明示或默示的保证 这包括但不限于对适销性或特定用途适用性的默示保证 本文假定您熟悉所演示的编程语言和用于创建和调试过程的工具 Microsoft 的支持工程师可以帮助解
  • 轮环(Ouroboros)世界观介绍,摘自Guide Book

    基于现实的架空世界观 这个游戏的世界观是基于以现代人的眼光来看待自身长久以来的发展与盛衰交替的事实 xff0c 而在此基础上构想出的简化的因果逻辑 xff0c 以及其外在的表现形式 祭祀 游戏根据中国古代的以国家为单位的大规模殉 祭奴隶的事
  • css背景图等比例缩放,盒子随背景图等比例缩放

    很多时候我们给网站了一个大banner 但是随着屏幕的变化 xff0c 背景会变形 xff0c 我们知道background size可以实现背景图等比例缩放 xff0c 但是 xff0c 我们想让下面的盒子根据缩放后背景图的高度 xff0
  • 如何用PS快速的批量制作连续号码数字编号图解

    如何用PS快速的批量制作连续号码数字编号图解 大家好 xff0c 今天太原博飞设计培训小编就告诉大家如用 PS 快速的制作连续数字编号 xff0c 在工作中尤其是大型活动的有时候制作连续的号码牌 xff0c 少还好 xff0c 如果上百上千
  • 我们评测了5个主流跨端框架,这是它们的区别

    最近前端届多端框架频出 xff0c 相信很多有代码多端运行需求的开发者都会产生一些疑惑 xff1a 这些框架都有什么优缺点 xff1f 到底应该用哪个 xff1f 作为 Taro 开发团队一员 xff0c 笔者想在本文尽量站在一个客观公正的
  • 大牛直播SDK-Windows RTMP/RTSP/本地FLV播放器使用说明 ...

    大牛直播播放器SDK相对推送SDK来说 xff0c 接口没有那么多 xff0c 不过客户95 以上的常规需求均已覆盖 xff0c 目前支持RTMP和RTSP直播播放 xff0c 还有本地flv文件回放 xff1a 大牛直播SDK播放端提供C
  • 交换机的配置文件备份到TFTP和FTP服务器

    1 构建拓扑 2 配置地址 Switch gt Switch gt en Switch conf t Switch config hostname 666 修改交换机名字 666 config interface vlan 1 进入虚拟接口
  • 推荐几款常用的Socks5代理软件

    一 Sockscap 荐 SocksCap是目前对网络游戏兼容性最好的代理工具之一 SocksCap32 软件是由美国 NEC USA Inc 公司出品的代理服务器第三方支持软件 拥有功能强大的 SOCKS 调度 xff0c 使用它就可以让
  • Nginx根据post参数转发请求 (OpenResty)

    最近有个需求 xff0c 需要nginx根据POST参数将请求转发到不同的后端 xff0c 调研后决定使用OpenResty xff08 Nginx 43 Lua xff09 作为代理服务器 写个小Demo location span cl
  • Windows 10访问共享时提示“过时的SMB1协议”的修复办法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 公司有台Windows XP老版本系统的文件共享服务器 xff0c 前段时间好好的能正常访问 xff0c 今天访问时突然提示 因为文件共享不安全 xff0c 所以你不能连接
  • 关于Video Src 带有 blob:http的视频如何下载的问题

    我们如果使用爬虫 xff0c 想爬取一些视频的时候 xff0c 会发现一些网站提供的视频链接打开是 404 xff1b span class hljs tag lt span class hljs name video span span
  • Wcf 双工通信的应用

    概述 双工 xff08 Duplex xff09 模式的消息交换方式体现在消息交换过程中 xff0c 参与的双方均可以向对方发送消息 基于双工MEP消息交换可以看成是多个基本模式下 xff08 比如请求 回复模式和单项模式 xff09 消息

随机推荐

  • Foxit PDF Reader能有效升级日文包

    Foxit Reader 原名 Foxit PDF Reader xff0c 是一款 PDF文档阅读软件 xff0c 它具有比Adobe Reader更加小巧的身材 xff0c 更加快速的速度 xff0c 以及更加丰富的插件 xff0c 完
  • JIRA学习

    Jira是Atlassian公司出品的一款事务管理软件 无论是 需求 xff0c 还是 BUG xff0c 或是 任务 xff0c 都是 事务 的一种 xff0c 所以Jira可以胜任非常多的角色 xff1a 需求管理 缺陷跟踪 任务管理等
  • python 面向对象编程

    面向对象与面向过程 参考链接 xff1a https www liaoxuefeng com wiki 0014316089557264a6b348958f449949df42a6d3a2e542c000 0014318645694388f
  • pycharm调整代码长度分割线

    1 File gt Settings gt Code Style gt Right margin columns 的值为80 xff0c 大功告成 2 具体设置的数值可以根据个人电脑的屏幕大小而定 xff0c 如果屏幕比较大可以设置的长一些
  • ppt点击文字出现图片,再次点击消失

    实现效果 xff1a 在PPT一个页面的任意位置 xff0c 单击左键 xff0c 出现图片 xff1b 在图片上 xff0c 单击左键 xff0c 图片消失 实现思路 xff1a 给图片做两个动画 xff0c 一个进入 xff0c 文字作
  • OC中APPDelegate[[UIApplication shareApplication]delegate]]Swift实现

    直接上代码 xff1a var myDelegate AppDelegate myDelegate 61 UIApplication sharedApplication delegate as AppDelegate
  • 安装好Pycharm后如何配置Python解释器简易教程

    这两天有许多Python小白加入学习群 xff0c 并且问了许多关于Pycharm基本使用的问题 xff0c 今天小编就以配置Python解释器的问题给大家简单絮叨一下 1 一般来说 xff0c 当我们启动Pycharm xff0c 如果P
  • MySQL net start mysql 发生系统错误5 解决办法

    产生的原因是权限不够 用管理员权限打开命令提示符就OK 啦 Win10解决办法 xff1a 使用快捷键win 43 x xff0c 或右击开始图标 xff0c 打开命令提示符 xff08 管理员 xff09 就解决啦
  • Docker查看远端仓库的标签工具

    背景 最近入坑了docker xff0c 比如本地想要启动一个elastic容器的话 xff0c 直接通过以下命令即可快速启动一个elasticsearch的实例 docker run d p 9200 9200 p 9300 9300 n
  • 互斥锁mutex的简单实现

    mutex一般用于为一段代码加锁 xff0c 以保证这段代码的原子性 xff08 atomic xff09 操作 xff0c 即 xff1a 要么不执行这段代码 xff0c 要么将这段代码全部执行完毕 例如 xff0c 最简单的并发冲突问题
  • Exception in thread "main" java.lang.NoClassDefFoundError: XXX

    Exception in thread 34 main 34 java lang NoClassDefFoundError XXX编译时没有报错 xff0c 一运行就不听话 网上找了一大堆 xff0c 各种解决方案都不是适合我 xff0c
  • 分享几个免费IP地址查询API接口

    1 IP地址查询接口 xff1a http apis juhe cn ip ip2addr 要先去https www juhe cn docs api 申请APPKEY 2 新浪的IP地址查询接口 xff1a http int dpool
  • 解决Cannot read property 'range' of null 错误

    为什么80 的码农都做不了架构师 xff1f gt gt gt vue工程npm run serve start dev启动时 xff0c node modules文件报 xff1a Cannot read property 39 rang
  • Gitlab Pipelines一直无法通过的临时解决办法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 新Gitlab系统是自己搭建的 xff0c 为了使用pages功能 xff0c 因为少于8 8版本貌似就不能使用 xff01 下一篇我会补充 xff0c 毕竟是转发的 xf
  • Generate Parentheses

    Given n pairs of parentheses write a function to generate all combinations of well formed parentheses For example given
  • C++11新特性不完全测试

    摘要 Lambda auto 统一初始化 xff0c 智能指针 xff0c Regex Random function and bind xff0c hash map 右值引用和Move语义 并发 多线程库 发布 阅读全文 Richard
  • matlab练习程序(生成高斯图像)

    cl m 61 31 n 61 31 img 61 zeros m 43 1 n 43 1 img 61 double img pi 61 3 1415926 sigma 61 10 for i 61 m 2 m 2 for j 61 n
  • Ubuntu远程桌面xrdp方法

    xrdp方式 xff0c 该方法支持多用户登录并远程桌面 首先在Ubuntu上安装GNOME 界面 xff0c 在终端输入命令 xff1a sudo apt get install gnome panel 安装完成后注销用户 点击自己用户的
  • Linux通过ssh传输文件

    一 scp是什么 scp是secure copy的简写 xff0c scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令 用于在Linux下进行远程拷贝文件的命令 xff0c 和它类似的命令有cp xff0c 不过cp只是在本机
  • 认识CoreData-基础使用

    第一篇文章中并没有讲CoreData的具体用法 xff0c 只是对CoreData做了一个详细的介绍 xff0c 算是一个开始和总结吧 这篇文章中会主要讲CoreData的基础使用 xff0c 以及在使用中需要注意的一些细节 因为文章中会插