IOS中完成块的后台任务

我正在做IOS中的一些数据库操作。 基本上我想在后台线程中做到这一点。 我尝试使用GCD 。 但是对于我来说问题是我想在完成之后从这个过程中获得一些价值。 在向数据库插入项目之前说我检查项目是否已经存在。 请参阅下面的代码

__block Boolean isExisting = false; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) { NSString *path = [SqliteManager initDatabase]; if(sqlite3_open([path UTF8String], &database) == SQLITE_OK) { NSString *query = [NSString stringWithFormat:@"select count (campaignId) from POTC where Id='%@' and taskid='%@' and pocId='%@' and userId='%@'",[submission.campaignId stringRepresentation],[submission.taskId stringRepresentation],[submission.pocId stringRepresentation],[[UUID UUIDWithString:submission.userId] stringRepresentation]]; const char *sql = [query cStringUsingEncoding:NSASCIIStringEncoding]; sqlite3_stmt *selectStatement; if (sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL) == SQLITE_OK) { while (sqlite3_step(selectStatement) == SQLITE_ROW) { if (sqlite3_column_int(selectStatement, 0) >0) { isExisting = true; break; } } sqlite3_finalize(selectStatement); } sqlite3_close(database); } return isExisting; }); 

但上面的代码与返回语句不会工作作为调度asynchronous期待一个无效的代码块。 我怎么能在IOS中实现相同的? 有没有类似于IOS中的animation完成块?

该块必须有一个返回types的void,因为无处可以将值返回到asynchronous块中。

variablesisExisting是合格的__block ,这意味着只要块分配给它就会被设置。 不幸的是,一旦主线程退出了范围,主线程将无法访问它。 谨慎的做法是让你的块调用另一个方法(或者函数或者块)来设置asynchronous块完成后你知道的variables或属性。

例如,您可以在应用程序委托上有一个方法来完成调用。

 // in your appDelegate implementation -(void) updateUIAfterDatabaseUpdate: (bool) isExisting { if (isExisting) { // eg display an error } else { // successful update } } // The update code dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) { bool isExisting = false; NSString *path = [SqliteManager initDatabase]; if(sqlite3_open([path UTF8String], &database) == SQLITE_OK) { // Snipped for clarity } dispatch_async(dispatch_get_main_queue(), ^(void) { [appDelegate updateUIAfterDatabaseUpdate: isExisting] ; }); }); 

主队列上的调度确保在主线程中调用该方法,以便可以执行UI更新。

也许你应该用一个完成块创build一个函数。

我定义这样的地雷:

 typedef void (^myBlock)(type1 param1, type2 param2); -(void)myAsyncFunctionWithParam:(id)paramSend withCompletionBlock:(myBlock)returningBlock { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //here everything you want to do // especially defining 2 parameters to return (let them be p1 & p2) dispatch_async(dispatch_get_main_queue(), ^{ returningBlock(p1,p2); }); }); } 

你可以像这样使用它:

 [self myAsyncFunctionWithParam:ps withCompletionBlock:^(type1 paramToUse1, type2 paramToUse2) { //You can use here paramToUse1 and paramToUse2 } ]; 

你可以使用任何你想要的types在块中的types:NSString,NSDate,…(如果需要,不要原谅*)

你不必返回一些东西,因为isExisting会变成true,如果你在块执行完成后访问它的值,它将返回true。

你正在想的方式失去了后台线程的好处:)。 你应该重构你的程序以更好地适应asynchronous模式。 您可以asynchronous启动后台工作,然后完成后,您可以向接收方发送消息以完成其他工作。 例如,在你的代码中,你可以使用通知或简单的消息发送。 喜欢这个 :

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) { NSString *path = [SqliteManager initDatabase]; if(sqlite3_open([path UTF8String], &database) == SQLITE_OK) { NSString *query = [NSString stringWithFormat:@"select count (campaignId) from POTC where Id='%@' and taskid='%@' and pocId='%@' and userId='%@'",[submission.campaignId stringRepresentation],[submission.taskId stringRepresentation],[submission.pocId stringRepresentation],[[UUID UUIDWithString:submission.userId] stringRepresentation]]; const char *sql = [query cStringUsingEncoding:NSASCIIStringEncoding]; sqlite3_stmt *selectStatement; if (sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL) == SQLITE_OK) { while (sqlite3_step(selectStatement) == SQLITE_ROW) { if (sqlite3_column_int(selectStatement, 0) >0) { // Here you can send the notification with the data you want. break; } } sqlite3_finalize(selectStatement); } sqlite3_close(database); } return isExisting; });