`

ios 任务、线程、定时器

 
阅读更多

一:operations(任务)

 

cocoa提供了三种不同的operations

 

1:Block operations(NSBlockOperation
These facilitate the execution of one or more block objects.

 

 

#import <UIKit/UIKit.h>
@interface 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 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	/* Here is our block */
	NSBlockOperation *newBlockOperation = [NSBlockOperation blockOperationWithBlock:^{
							NSLog(@"Main Thread = %@", [NSThread mainThread]);
							NSLog(@"Current Thread = %@", [NSThread currentThread]);
							NSUInteger counter = 0;
							for (counter = 0;counter < 1000;counter++){
								NSLog(@"Count = %lu", (unsigned long)counter);
							}
								}];

	/* Make sure we keep the reference somewhere */
	self.simpleOperation = newBlockOperation;
	
	/* Start the operation */
	[self.simpleOperation start];

	/* Print something out just to test if we have to wait
	for 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:self selector:@selector(simpleOperationEntry:) object:simpleObject];

[newOperation  start];

 

 

调用start方法执行改任务

 

#import <UIKit/UIKit.h>
@interface 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 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

	NSNumber *simpleObject = [NSNumber numberWithInteger:123];
	NSInvocationOperation *newOperation =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(simpleOperationEntry:) object:simpleObject];
	self.simpleOperation = newOperation;
	[newOperation release];

	[self.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.

 

 

@interface MyTask : NSOperation { 
    int operationId; 
}

@property int operationId;

@end

 

这里的operationId属性不是必须的

 

@implementation MyTask

@synthesize operationId;

- (void)main{ 
    NSLog(@"task %i run … ",operationId); 
    [NSThread sleepForTimeInterval:10]; 
    NSLog(@"task %i is finished. ",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 对象被放进主线程的自动释放池,在主线程销毁是被自动释放

 

 

 


 

分享到:
评论

相关推荐

    在主线程上创建精准定时器

    在主线程上面创建定准定时器,一个简单的demo

    IOS计时器设计

    多种方法实现计时器,包括通信获取服务器端系统时间,多线程实现,NSTimer实现等等 http://blog.csdn.net/dingxiaowei2013/article/details/9864279

    iOS App使用GCD导致的卡顿现象及解决方法

    最近在调研 iOS app 中存在的各种卡顿现象以及解决方法。 iOS App 出现卡顿(stall)的概率可能超出大部分人的想象,尤其是对于大公司旗舰型 App。一方面是由于业务功能不停累积,各个产品团队之间缺乏协调,大家都...

    iOS GCD-Program-master

    ios 完美使用gcd 哪怕菜鸟都会使用的线程操作,队列,定时器,等待等

    iOS中使用NSProgress类来创建UI进度条的方法详解

    单任务进度的监听是NSProgress最简单的一种运用场景,我们来用定时器模拟一个耗时任务,示例代码如下: @interface ViewController () { NSProgress * progress; } @end @implementation ViewController - (void)...

    ios-仿QQ、微信表情下落动画.zip

    使用CADisplayLink创建一个刷新定时器,设置帧刷新调用方法时间,然后加入mainRunLoop里面执行。具体加在主线程的RunLoop还是子线程的RunLoop可根据自己项目进行修改。

    ios开发记录

    //判断定时器的指针是否存在(定时器的对象是否存在) if(_tim){ //必须在定时器失效以后将定时器的指针至为空 [_tim invalidate]; invalidate使…无效 _tim=nil; }else{ _tim=[NSTimer ...

    leetcode站台停留次数-iOS-Ready-For-Interview:认真工作!热爱生活!

    6.NSTimer定时器 准备资料: 《iOS与OS X多线程和内存管理》《52个有效方法》 实践: Swift 《objccn-swifter-tips》《objccn-advanced-swift》 UIKit UIView、UIViewController生命周期 事件响应链 UItableView优化 ...

    基于C++11线程池技术简单易用的轻量级网络编程框架源码.zip

    使用线程实现的简单易用的定时器。 信号量。 线程组。 简单易用的线程池,可以异步或同步执行任务,支持functional 和 lambad表达式。 工具库 文件操作。 std::cout风格的日志库,支持颜色高亮、代码定位、异步打印...

    ios-鹏哥哥放大镜.zip

    鹏哥哥放大镜 封装好 线程安全 无泄漏 简单易用 移植性好 使用中有问题 请前去GitHub与我联系 感谢您的使用 对您有帮助的话 送我一颗星星可好 使用简介: 1.PGGMagnigierView导入放大镜类 也可以在这里面进行镜框...

    Objective-C开发范例代码大全

    ● 构建使用了日期、定时器与内存管理的应用 ● 如何在其他平台上使用Objective-C  凭借深入的代码示例与清晰的解释说明,本书将帮助你轻松解决iOS开发人员每天都 会面临的挑战。通过使用书中介绍的知识与技能,...

    Unity3D 2018 最新最全800个脚本教程

    Unity3D音乐开关与音量条 Unity3D教程:GUILayout.Window和GUI.Window的区别 在游戏中改变地形高度 教你如何创建unity3d多个定时器,以及定时器的其他操作 Unity3D使用LitJson解析服务器上的JSON IOS下文件保存和...

    ZLToolKit:一个基于C++11的轻量级网络框架,基于线程池技术可以实现大并发网络IO

    一个基于C++11简单易用的轻量级网络编程框架项目特点基于...线程库使用线程实现的简单易用的定时器。信号量。线程组。简单易用的线程池,可以异步或同步执行任务,支持functional 和 lambad表达式。工具库文件操作。std

    iOS之UITableView计时器的实现方式总结(NSTimer、DispatchSource、CADisplayLink)

    今天博客中所涉及的内容并不复杂,都是一些平时常见的一些问题,通过这篇博客算是对UITableView中使用定时器的几种方式进行总结。本篇博客会给出在TableView中使用NSTimer或者DispatchSourcer中常见的五种方式。当然...

    多样式自定义无限滚动

    源码CorePPTVC,幻灯终结者:超简单、酷且炫、多样式、...支持定时器自动切换且界面push定时器停止. .8.支持幻灯点击事件回调. .9.幻灯框架可任意扩展与自定义. .9.内部很多控件均可高度自定义样式,灵活性非常大.

    CorePPTVC:幻灯终结者:超简单、酷且炫、多样式、自定义!

    支持定时器自动切换且界面push定时器停止..8.支持幻灯点击事件回调..9.幻灯框架可任意扩展与自定义..9.内部很多控件均可高度自定义样式,灵活性非常大.使用示例 //定义数据模型。如果数据来自远程服务器,可一键转...

Global site tag (gtag.js) - Google Analytics