相当于Android的AsyncTask的iOS / Objective-C
我熟悉在Android中使用AsyncTask
:创build一个子类,在子类的实例上调用execute
,并在UI线程或主线程上调用onPostExecute
。 iOS中有什么等价物?
回答原始问题:
Grand Central Dispatch(GCD)提供了一种在后台执行任务的机制,尽pipe它与AsyncTask在结构上有所不同。 要asynchronous执行某些操作,只需创build一个队列(如线程),然后将一个块传递给dispatch_async()
以在后台执行。 我发现它比AsyncTask整洁,因为没有子类涉及; 无论你想在后台执行哪个代码,它都或多或less是即插即用的。 一个例子:
dispatch_queue_t queue = dispatch_queue_create("com.yourdomain.yourappname", NULL); dispatch_async(queue, ^{ //code to be executed in the background });
其他要点:
1)callback
如果您想在后台执行任务并在后台任务完成时更新UI(或者在另一个线程上执行某些操作),则可以简单地嵌套调度调用:
dispatch_queue_t queue = dispatch_queue_create("com.yourdomain.yourappname", NULL); dispatch_async(queue, ^{ //code to be executed in the background dispatch_async(dispatch_get_main_queue(), ^{ //code to be executed on the main thread when background task is finished }); });
2)全局队列
创build队列时,还可以使用dispatch_get_global_queue()
函数获取具有一定优先级的全局调度队列(如DISPATCH_QUEUE_PRIORITY_HIGH
)。 这些队列是普遍可访问的,并且在您想要将多个任务分配给同一个线程/队列时非常有用。 请注意,内存是完全由iOSpipe理的。
3)记忆
内存pipe理和调度队列有时会有一些混淆,因为他们有自己的dispatch_retain
/ dispatch_release
函数。 但是,请放心,它们被ARC视为Objective-C对象,因此您不必担心调用这些函数。 参照rob mayoff关于GCD和ARC 的很好的回答 ,你可以看到文档描述了GCD队列与Objective-C对象的等价关系:
* By default, libSystem objects such as GCD and XPC objects are declared as * Objective-C types when building with an Objective-C compiler. This allows * them to participate in ARC, in RR management by the Blocks runtime and in * leaks checking by the static analyzer, and enables them to be added to Cocoa * collections. * * NOTE: this requires explicit cancellation of dispatch sources and xpc * connections whose handler blocks capture the source/connection object, * resp. ensuring that such captures do not form retain cycles (eg by * declaring the source as __weak). * * To opt-out of this default behavior, add -DOS_OBJECT_USE_OBJC=0 to your * compiler flags. * * This mode requires a platform with the modern Objective-C runtime, the * Objective-C GC compiler option to be disabled, and at least a Mac OS X 10.8 * or iOS 6.0 deployment target.
4)多任务/块
我将补充说,如果一个任务在多个asynchronous活动完成之前无法继续,那么GCD有一个分组接口支持同步多个asynchronous块。 JörnEyrich和ɲeuroburɳ 在这里提供了对这个主题的慷慨解释。 如果您需要此function,我强烈build议花几分钟时间仔细阅读他们的答案,并了解他们之间的差异。
如果您非常喜欢这个文档 ,那么这个文档就有很多这方面的信息。
在iOS中没有类,但是你可以使用队列来模拟它。 你可以打电话给:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Your code to execute in background... });
asynchronous任务,并在你的asynchronous代码调用下一个队列在视图中做一些事情…:
dispatch_async(dispatch_get_main_queue(), ^{ //Your code to execute on UIthread (main thread) });
然后,使用这两个队列,你可以创build一个asyncTask类,将这个类添加到你的项目来实现它们:
// // AsyncTask.h // // Created by Mansour Boutarbouch Mhaimeur on 25/10/13. // #import <Foundation/Foundation.h> @interface AsyncTask : NSObject - (void) executeParameters: (NSArray *) params; - (void) preExecute; - (NSInteger) doInBackground: (NSArray *) parameters; - (void) postExecute: (NSInteger) result; @end
// // AsyncTask.m // // Created by Mansour Boutarbouch Mhaimeur on 25/10/13. // #import "AsyncTask.h" @implementation AsyncTask - (void) executeParameters: (NSArray *) params{ [self preExecute]; __block NSInteger result; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ result = [self doInBackground:params]; dispatch_async(dispatch_get_main_queue(), ^{ [self postExecute:result]; }); }); } - (void) preExecute{ //Method to override //Run on main thread (UIThread) } - (NSInteger) doInBackground: (NSArray *) parameters{ //Method to override //Run on async thread (Background) return 0; } - (void) postExecute: (NSInteger) result{ //Method to override //Run on main thread (UIThread) } @end
这是我在一个项目中使用的一个例子:
#import "AsyncTask.h" #import "Chat.h" @interface SendChatTask : AsyncTask{ NSArray * chatsNotSent; } @end
#import "SendChatTask.h" @implementation SendChatTask - (void) preExecute{ //Method to override } - (NSInteger) doInBackground: (NSArray *) parameters{ //Method to override NSString *sendChatsURL = [NSString stringWithFormat:@"%@%@%@",HOST, NAMESPACE,URL_SEND_CHAT]; chatsNotSent = [parameters objectAtIndex:0]; NSString *response; NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; //... NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[ChatJSONParser wrapChatArray: chatsNotSent] options:0 error:&error]; NSString *JSONString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding]; [params setObject:JSONString forKey:@"chats"]; response = [HTTPClient executePOST:sendChatsURL parameters:params]; if([respuesta isEqualToString:@"true"]){ return 1; }else{ return -1; } } - (void) postExecute: (NSInteger) result{ //Method to override if (result == 1) { for (Chat *chat in chatsNotSent) { chat.state = STATE_NOT_SENT; [chat save]; AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; [appDelegate refreshChat]; } } else { } } @end
接下来的电话:
[[[SendChatTask alloc] init] executeParameters:[NSArray arrayWithObjects: chatsNotSent, nil]];
您可以添加一个publishProgress()
更新方法和相应的…我暂时不使用它,因为我在后台服务中调用我的asynchronous任务。
我希望这是有帮助的。
如果您定位iOS版本较早(iOS 4为Grand Central Dispatch),则可以使用NSObject performSelector方法
-
在后台执行线程performSelectorInBackground:withObject:
-
并在MainThread上执行 performSelectorOnMainThread:withObject:waitUntilDone:
这是一个例子:
[self performSelectorInBackground:@selector(executeInBackground) withObject:nil]; -(void) executeInBackground { NSLog(@"executeInBackground"); [self performSelectorOnMainThread:@selector(executeOnMainThread) withObject:nil waitUntilDone:NO]; } -(void) executeOnMainThread { NSLog(@"executeOnMainThread"); }
Swift 3
在Android中,当我想要在后台线程上运行一个任务,然后在完成后更新UI时,我使用了AsyncTask
( 示例 )。 现在,当我制作应用程序的iOS版本时,我使用Grand Central Dispatch (GCD)来做同样的事情。 以下是Swift如何完成的:
DispatchQueue.global(qos: .background).async { // code to be run on a background task DispatchQueue.main.async { // code to be run on the main thread after the background task is finished } }
笔记
- Grand Central调度教程Swift
- RecyclerView丢失
- Android短信接收器不工作
- 此Android SDK需要Android Developer Toolkit版本23.0.0或更高版本
- 如何在Android中实现可展开的面板?
- Android应用内结算:无法启动asynchronous操作,因为另一个asynchronous操作(正在进行)
- 如何将DecimalFormat的小数点分隔符从逗号更改为点/点?
- Android导航抽屉切换图标向右
- 在使用基于Gradle的configuration时,在Android Studio(IntelliJ)上运行简单的JUnittesting
- 在Mac OS X上安装Android SDK的位置?