gpt4 book ai didi

iphone - 使用文件 (CSV) 而不是使用 CoreData

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:08:24 24 4
gpt4 key购买 nike

我正在构建的一个应用程序包含一个包含数千个项目的目录,这些项目需要存储在手机上。目前我正在通过 CoreData 实现这一点,因为从逻辑上讲,它似乎是放置它的最佳位置。我正在使用 GCD 在后台运行 CoreData 插入进程并显示进度条/当前完成百分比。这按预期工作,但是对于仅 5000 个项目,在 iPhone 4 上需要 8 分钟才能完成。此应用程序将在 3GS 及更高版本上使用,并且在启动后更有可能包含 30/40 千个项目。因此,这个处理时间将非常长。

有什么方法可以使用 CSV 文件或其他文件进行搜索,而不是将每个项目都存储在 CoreData 中?我假设这样的方法会导致一些效率下降,但它会减少过多的等待时间。除非有另一种解决方案可以帮助解决这个问题。

谢谢。

编辑:我不确定如何在整个操作结束时保存上下文,因为它在循环中使用了单独的上下文。对此的任何建议将不胜感激。我不知道如何在这方面取得进展。

正在使用的插入代码

- (void) processUpdatesGCD {
NSArray *jsonArray=[NSJSONSerialization JSONObjectWithData:_responseData options:0 error:nil];
NSArray *products = [jsonArray valueForKey:@"products"];
NSArray *deletions;
if ([jsonArray valueForKey:@"deletions"] == (id)[NSNull null]){
self.totalCount = [products count];
} else {
deletions = [jsonArray valueForKey:@"deletions"];
self.totalCount = [products count] + [deletions count];
}

self.productDBCount = 0;

_delegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = _delegate.managedObjectContext;
self.persistentStoreCoordinator = [managedObjectContext persistentStoreCoordinator];
_managedObjectContext = managedObjectContext;



// Create a new background queue for GCD
dispatch_queue_t backgroundDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

for (id p in products) {

// id product = p;

// Dispatch the following code on our background queue
dispatch_async(backgroundDispatchQueue,
^{
id product = p;
// Because at this point we are running in another thread we need to create a
// new NSManagedContext using the app's persistance store coordinator

NSManagedObjectContext *backgroundThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];

NSFetchRequest *BGRequest = [[NSFetchRequest alloc] init];
NSLog(@"Running.. (%@)", product);
[BGRequest setEntity:[NSEntityDescription entityForName:@"Products" inManagedObjectContext:backgroundThreadContext]];
[BGRequest setIncludesSubentities:NO];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"codes == %@", [product valueForKey:@"product_codes"]];
[BGRequest setPredicate:predicate];

NSError *err;
NSArray *results = [backgroundThreadContext executeFetchRequest:BGRequest error:&err];

if (results.count == 0){
// Product doesn't exist with code, make a new product

NSLog(@"Product not found for add/update (%@)", [product valueForKey:@"product_name"]);

NSManagedObject* newProduct;
newProduct = [NSEntityDescription insertNewObjectForEntityForName:@"Products" inManagedObjectContext:backgroundThreadContext];

[newProduct setValue:[product valueForKey:@"product_name"] forKey:@"name"];
[newProduct setValue:[product valueForKey:@"product_codes"] forKey:@"codes"];

if ([product valueForKey:@"information"] == (id)[NSNull null]){
// No information, NULL
[newProduct setValue:@"" forKey:@"information"];
} else {
NSString *information = [product valueForKey:@"information"];
[newProduct setValue:information forKey:@"information"];

}

} else {
NSLog(@"Product found for add/update (%@)", [product valueForKey:@"product_name"]);
// Product exists, update existing product
for (NSManagedObject *r in results) {
[r setValue:[product valueForKey:@"product_name"] forKey:@"name"];

if ([product valueForKey:@"information"] == (id)[NSNull null]){
// No information, NULL
[r setValue:@"" forKey:@"information"];
} else {
NSString *information = [product valueForKey:@"information"];
[r setValue:information forKey:@"information"];
}

}

}



// Is very important that you save the context before moving to the Main Thread,
// because we need that the new object is writted on the database before continuing
NSError *error;

if(![backgroundThreadContext save:&error])
{
NSLog(@"There was a problem saving the context (add/update). With error: %@, and user info: %@",
[error localizedDescription],
[error userInfo]);
}


// Now let's move to the main thread
dispatch_async(dispatch_get_main_queue(), ^
{
// If you have a main thread context you can use it, this time i will create a
// new one
// NSManagedObjectContext *mainThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
// [mainThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];

self.productDBCount = self.productDBCount + 1;
float progress = ((float)self.productDBCount / (float)self.totalCount);
int percent = progress * 100.0f;
// NSNumber *progress = [NSNumber numberWithFloat:((float)self.productDBCount / (float)self.totalCount)];
self.downloadUpdateProgress.progress = progress;
self.percentageComplete.text = [NSString stringWithFormat:@"%i", percent];
NSLog(@"Added / updated product %f // ProductDBCount: %i // Percentage progress: %i // Total Count: %i", progress, self.productDBCount, percent, self.totalCount);
if (self.productDBCount == self.totalCount){
[self updatesCompleted:[jsonArray valueForKey:@"last_updated"]];
}

});
});

}


if ([deletions count] > 0){
for (id d in deletions){
dispatch_async(backgroundDispatchQueue,
^{
id deleted = d;
// Because at this point we are running in another thread we need to create a
// new NSManagedContext using the app's persistance store coordinator

NSManagedObjectContext *backgroundThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];

NSFetchRequest *BGRequest = [[NSFetchRequest alloc] init];
// NSLog(@"Running.. (%@)", deleted);
[BGRequest setEntity:[NSEntityDescription entityForName:@"Products" inManagedObjectContext:backgroundThreadContext]];
[BGRequest setIncludesSubentities:NO];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"codes == %@", [deleted valueForKey:@"product_codes"]];
[BGRequest setPredicate:predicate];

NSError *err;
NSArray *results = [backgroundThreadContext executeFetchRequest:BGRequest error:&err];

if (results.count == 0){
// Product doesn't exist with code, make a new product

NSLog(@"Product not found, can't delete.. %@", [deleted valueForKey:@"product_name"]);

} else {
NSLog(@"Product found, deleting: %@", [deleted valueForKey:@"product_name"]);
// Product exists, update existing product
for (NSManagedObject *r in results) {
[backgroundThreadContext deleteObject:r];
}

}



// Is very important that you save the context before moving to the Main Thread,
// because we need that the new object is writted on the database before continuing
NSError *error;

if(![backgroundThreadContext save:&error])
{
NSLog(@"There was a problem saving the context (delete). With error: %@, and user info: %@",
[error localizedDescription],
[error userInfo]);
}


// Now let's move to the main thread
dispatch_async(dispatch_get_main_queue(), ^
{

self.productDBCount = self.productDBCount + 1;
float progress = ((float)self.productDBCount / (float)self.totalCount);
int percent = progress * 100.0f;
// NSNumber *progress = [NSNumber numberWithFloat:((float)self.productDBCount / (float)self.totalCount)];
self.downloadUpdateProgress.progress = progress;
self.percentageComplete.text = [NSString stringWithFormat:@"%i", percent];
NSLog(@"Deleted product %f // ProductDBCount: %i // Percentage progress: %i // Total Count: %i", progress, self.productDBCount, percent, self.totalCount);
if (self.productDBCount == self.totalCount){
[self updatesCompleted:[jsonArray valueForKey:@"last_updated"]];
}

/*
*
* Change the completion changes to a method. Check to see if the total number of products == total count. If it does, run the completion method.
*
*/

});
});
}
}


}

将IF放在dispatch里面,最后运行一个save

    // Create a new background queue for GCD
dispatch_queue_t backgroundDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
// id product = p;

// Dispatch the following code on our background queue
dispatch_async(backgroundDispatchQueue,
^{

NSManagedObjectContext *backgroundThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];

for (id p in products) {
id product = p;
// Because at this point we are running in another thread we need to create a
// new NSManagedContext using the app's persistance store coordinator



NSFetchRequest *BGRequest = [[NSFetchRequest alloc] init];
NSLog(@"Running.. (%@)", product);
[BGRequest setEntity:[NSEntityDescription entityForName:@"Products" inManagedObjectContext:backgroundThreadContext]];
[BGRequest setIncludesSubentities:NO];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"codes == %@", [product valueForKey:@"product_codes"]];
[BGRequest setPredicate:predicate];

NSError *err;
NSArray *results = [backgroundThreadContext executeFetchRequest:BGRequest error:&err];

if (results.count == 0){
// Product doesn't exist with code, make a new product

NSLog(@"Product not found for add/update (%@)", [product valueForKey:@"product_name"]);

NSManagedObject* newProduct;
newProduct = [NSEntityDescription insertNewObjectForEntityForName:@"Products" inManagedObjectContext:backgroundThreadContext];

[newProduct setValue:[product valueForKey:@"product_name"] forKey:@"name"];
[newProduct setValue:[product valueForKey:@"product_codes"] forKey:@"codes"];

if ([product valueForKey:@"information"] == (id)[NSNull null]){
// No information, NULL
[newProduct setValue:@"" forKey:@"information"];
} else {
NSString *information = [product valueForKey:@"information"];
[newProduct setValue:information forKey:@"information"];

}

} else {
NSLog(@"Product found for add/update (%@)", [product valueForKey:@"product_name"]);
// Product exists, update existing product
for (NSManagedObject *r in results) {
[r setValue:[product valueForKey:@"product_name"] forKey:@"name"];

if ([product valueForKey:@"information"] == (id)[NSNull null]){
// No information, NULL
[r setValue:@"" forKey:@"information"];
} else {
NSString *information = [product valueForKey:@"information"];
[r setValue:information forKey:@"information"];
}

}

}



// Is very important that you save the context before moving to the Main Thread,
// because we need that the new object is writted on the database before continuing


// Now let's move to the main thread
dispatch_async(dispatch_get_main_queue(), ^
{
// If you have a main thread context you can use it, this time i will create a
// new one
// NSManagedObjectContext *mainThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
// [mainThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];


self.productDBCount = self.productDBCount + 1;
float progress = ((float)self.productDBCount / (float)self.totalCount);
int percent = progress * 100.0f;
// NSNumber *progress = [NSNumber numberWithFloat:((float)self.productDBCount / (float)self.totalCount)];
self.downloadUpdateProgress.progress = progress;
self.percentageComplete.text = [NSString stringWithFormat:@"%i", percent];
NSLog(@"Added / updated product %f // ProductDBCount: %i // Percentage progress: %i // Total Count: %i", progress, self.productDBCount, percent, self.totalCount);

NSDate *currentProcessedDate = [NSDate date];
NSTimeInterval timeSinceStarted = [currentProcessedDate timeIntervalSinceDate:self.startProcessing];
NSInteger remainingProcesses = self.totalCount - self.productDBCount;
float timePerProcess = timeSinceStarted / (float)self.productDBCount;
float remainingTime = timePerProcess * (float)remainingProcesses;
self.timeRemaining.text = [NSString stringWithFormat:@"ETA: %0.0f minutes", fmodf(remainingTime, 60.0f)];

if (self.productDBCount == self.totalCount){
[self updatesCompleted:[jsonArray valueForKey:@"last_updated"]];
}

/*
*
* Change the completion changes to a method. Check to see if the total number of products == total count. If it does, run the completion method.
*
*/
});

}

NSError *error;

if(![backgroundThreadContext save:&error])
{
NSLog(@"There was a problem saving the context (add/update). With error: %@, and user info: %@",
[error localizedDescription],
[error userInfo]);
}


});

最佳答案

好的,这是你的问题。

每次插入记录时,都会对上下文进行保存操作。现在,不要这样做,那会花费很多时间。

保存一次,在循环结束时,不是每次插入记录时。

关于iphone - 使用文件 (CSV) 而不是使用 CoreData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17185270/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com