一:operations(任務)
cocoa提供了三種不同的operations
1:Block operations(NSBlockOperation)
These facilitate the execution of one or more block objects.
- #import <UIKit/UIKit.h>
- @inter<span>f</span>ace OperationsAppDelegate : NSObject <UIApplicationDelegate> {
- UIWindow *window;
- NSBlockOperation *simpleOperation;
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @property (nonatomic, retain) NSBlockOperation *simpleOperation;
- @end
- #import "OperationsAppDelegate.h"
- @implementation OperationsAppDelegate
- @synthesize window;
- @synthesize simpleOperation;
- - (BOOL) application:(UIApplication *)application did<span>F</span>inishLaunchingWithOptions:(NSDictionary *)launchOptions {
- /* Here is our block */
- NSBlockOperation *newBlockOperation = [NSBlockOperation blockOperationWithBlock:^{
- NSLog(@"Main Thread = %@", [NSThread mainThread]);
- NSLog(@"Current Thread = %@", [NSThread currentThread]);
- NSUInteger counter = 0;
- <span>f</span>or (counter = 0;counter < 1000;counter++){
- NSLog(@"Count = %lu", (unsigned long)counter);
- }
- }];
- /* Make sure we keep the re<span>f</span>erence somewhere */
- sel<span>f</span>.simpleOperation = newBlockOperation;
- /* Start the operation */
- [sel<span>f</span>.simpleOperation start];
- /* Print something out just to test i<span>f</span> we have to wait
- <span>f</span>or the block to execute its code or not */
- NSLog(@"Main thread is here");
- [window makeKeyAndVisible];
- return YES;
- }
- - (void)dealloc {
- [simpleOperation release];
- [window release];
- [super dealloc];
- }
- @end
2:Invocation operations(NSInvocationOperation)
These allow you to invoke a method in another, currently existing object.
NSNumber *simpleObject = [NSNumber numberWithInteger:123];
NSInvocationOperation *newOperation = [[NSInvocationOperation alloc] initWithTarget:selfselector:@selector(simpleOperationEntry:) object:simpleObject];
[newOperation start];
調用start方法執行改任務
- #import <UIKit/UIKit.h>
- @inter<span>f</span>ace OperationsAppDelegate : NSObject <UIApplicationDelegate> {
- UIWindow *window;
- NSInvocationOperation *simpleOperation;
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @property (nonatomic, retain) NSInvocationOperation *simpleOperation;
- @end
- - (void) simpleOperationEntry:(id)paramObject{
- NSLog(@"Parameter Object = %@", paramObject);
- NSLog(@"Main Thread = %@", [NSThread mainThread]);
- NSLog(@"Current Thread = %@", [NSThread currentThread]);
- }
- - (BOOL) application:(UIApplication *)application did<span>F</span>inishLaunchingWithOptions:(NSDictionary *)launchOptions {
- NSNumber *simpleObject = [NSNumber numberWithInteger:123];
- NSInvocationOperation *newOperation =[[NSInvocationOperation alloc] initWithTarget:sel<span>f</span> selector:@selector(simpleOperationEntry:) object:simpleObject];
- sel<span>f</span>.simpleOperation = newOperation;
- [newOperation release];
- [sel<span>f</span>.simpleOperation start];
- [window makeKeyAndVisible];
- return YES;
- }
- - (void)dealloc {
- [simpleOperation release];
- [window release];
- [super dealloc];
- }
3:Plain operations(簡單的任務)NSOperation的子類
These are plain operation classes that need to be subclassed. The code to be executed
will be written inside the main method of the operation object.
- @inter<span>f</span>ace MyTask : NSOperation {
- int operationId;
- }
- @property int operationId;
- @end
這里的operationId屬性不是必須的
- @implementation MyTask
- @synthesize operationId;
- - (void)main{
- NSLog(@"task %i run … ",operationId);
- [NSThread sleep<span>F</span>orTimeInterval:10];
- NSLog(@"task %i is <span>f</span>inished. ",operationId);
- }
- @end
必須
- (void)main;方法,[MyTask start]是執行main方法
二:任務隊列(NSOperationQueue)
NSOperationQueue *newOperationQueue = [[NSOperationQueue alloc] init];
[ newOperationQueue addOperation:Operation];
以上三種Operation都可以添加到NSOperationQueue中,添加后立即被執行。
NSOperationQueue 可以設置最大並行執行任務數。默認值為-1無限制。
三:多個任務之間存在依賴關系
設置方式:
[self.firstOperation addDependency:self.secondOperation];
dependency:附屬的意思
把secondOperation做為firstOperation的附屬。因此先執行secondOperation,再執行firstOperation 。
四:延時執行某個方法
1:performSelector:withObject:afterDelay:
- - (void) connectionHasFailedWithError:(NSError *)paramError onRemoteURL:(NSURL *)paramRemoteURL{
- /* We failed to download the file. Attempt to download it again after 3 seconds */
- [self performSelector:@selector(attemptToDownloadRemoteURL:) withObject:paramRemoteURL afterDelay:3.0f];
- }
- - (void) attemptToDownloadRemoteURL:(NSURL *)paramRemoteURL{
- /* Attempt to download the remote file again here by initializing
- a new connection ... */
- }
該方法只能接受一個參數。如果需要傳遞多個參數怎么辦呢???
讓selector調用的方法接受的參數類型修改為Dictionary類型。
(1)如果調用的selector不接受參數則,withObject:nil
(2) 通過performSelector:withObjcet:afterDelay調用的方法不能有返回值
2:取消延時執行的方法
(1)cancelPreviousPerformRequestsWithTarget:
(2) cancelPreviousPerformRequestsWithTarget:selector:object:
五:NSTimer
1:scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
2:invalidate
調用invalidate方法,不僅是釋放NSTimer,還釋放userinfo對象。
如果repeats設置為NO,NSTimer在調用完成之后就知道失效,隨即釋放userinfo對象
3:scheduledTimerWithTimeInterval:invocation:repeats:
- - (void) startPainting{
- SEL selectorToCall = @selector(paint:);
- NSMethodSignature *methodSignature = [[self class] instanceMethodSignatureForSelector:selectorToCall];
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
- [invocation setTarget:self];
- [invocation setSelector:selectorToCall];
- /* Start a scheduled timer now */
- NSTimer *newTimer =[NSTimer scheduledTimerWithTimeInterval:1.0
- invocation:invocation
- repeats:YES];
- self.paintingTimer = newTimer;
- }
4:timerWithTimeInterval:target:selector:userInfo:repeats:
(用該方式,需要把timer添加到runloop中)
- - (void) startPainting{
- NSTimer *newTimer = [NSTimer timerWithTimeInterval:1.0
- target:self
- selector:@selector(paint:)
- userInfo:nil
- repeats:YES];
- self.paintingTimer = newTimer;
- [[NSRunLoop currentRunLoop] addTimer:self.paintingTimer forMode:NSDefaultRunLoopMode];
- }
5:timerWithTimeInterval:invocation:repeats:
(用該方式,需要把timer添加到runloop中)
- - (void) startPainting{
- SEL selectorToCall = @selector(paint:);
- NSMethodSignature *methodSignature =[[self class] instanceMethodSignatureForSelector:selectorToCall];
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
- [invocation setTarget:self];
- [invocation setSelector:selectorToCall];
- NSTimer *newTimer = [NSTimer timerWithTimeInterval:1.0
- invocation:invocation
- repeats:YES];
- self.paintingTimer = newTimer;
- [[NSRunLoop currentRunLoop] addTimer:self.paintingTimer
- forMode:NSDefaultRunLoopMode];
- }
6:NSTimer 響應函數定義格式
並需有一個NSTimer *類型的參數
- - (void) paint:(NSTimer *)paramTimer{
- /* Do something here */
- NSLog(@"Painting");
- }
六:NSThread
1:initWithTarget:selector:object:
2:detachNewThreadSelector:toTarget: withObject:
以上兩種方式,selector調用的函數,必須聲明自己的NSAutoreleasePool
3:performSelectorInBackground: withObject:
一個簡單的方法來創建線程,而無需直接處理線程。
- [self performSelectorInBackground:@selector(thirdCounter) withObject:nil];
4:start
調用start方法啟動線程
5:cancel
調用cancel方法,並把變量賦值為nil
6:cancel vs exit
對於線程調用cancel方法停止,不要調用exit,因為exit方法沒有給線程清理自己並釋放資源的時間
7:線程的內存泄露
- - (void) newThreadEntryPoint{
- /* A thread without an autorelease pool to test the following code */
- //NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- /* This WILL cause a memory leak */
- [self performSelector:@selector(allocateSomething)];
- /* This will NOT cause a memory leak */
- [self performSelectorOnMainThread:@selector(allocateSomething)
- withObject:nil
- waitUntilDone:YES];
- //[pool release];
- }
- - (void) allocateSomething{
- NSBundle *mainBundle = [NSBundle mainBundle];
- NSString *imagePath = [mainBundle pathForResource:@"MyImage" ofType:@"png"];
- NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
- UIImage *myImage = [[[UIImage alloc] initWithData:imageData] autorelease];
- /* Do something with the image here */
- }
- - (void)viewDidLoad {
- [NSThread detachNewThreadSelector:@selector(newThreadEntryPoint)
- toTarget:self
- withObject:nil];
- }
UIImage *myImage = [[[UIImage alloc] initWithData:imageData] autorelease];-------------自動釋放池的范圍
/* This WILL cause a memory leak */
[self performSelector:@selector(allocateSomething)];
調用改方法myImage 對象被添加進該新建線程的自動釋放池,但因為在這里沒有聲明NSAutoreleasePool 造成內存泄露
/* This will NOT cause a memory leak */
[self performSelectorOnMainThread:@selector(allocateSomething)
withObject:nil
waitUntilDone:YES];
調用改方法myImage 對象被放進主線程的自動釋放池,在主線程銷毀是被自動釋放