这是我目前正在开发的源文件。这个类背后的想法是包含一个目标对象和选择器,它将在传递给 scheduleInCFRunLoop的任何CFRunLoop中调用。我需要这个重复循环而不消耗 iPhone 上的所有可用处理时间。任何关于完成的帮助都是最有帮助的,我花了一整天的时间在网上冲浪,试图找到有关自定义 CFRunLoop 源的有用信息,但我还没有找到任何对完成这门课程有用的东西。
RunLoopContext.h
//
// RunLoopContext.h
// ETAClient-iPhoneOS
//
// Created by Daniel Reed on 9/7/10.
// Copyright 2010 N/a. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RunLoopContext : NSObject
{
id target;
SEL selector;
CFRunLoopSourceContext context;
CFRunLoopSourceRef source;
CFRunLoopRef runLoop;
CFStringRef mode;
}
#pragma mark -
#pragma mark Property directives
@property (assign) id target;
@property (assign) SEL selector;
@property (readonly) CFRunLoopSourceContext context;
@property (readonly) CFRunLoopSourceRef source;
@property (readonly) CFRunLoopRef runLoop;
#pragma mark -
#pragma mark Custom initializers
-(id) initWithTarget: (id) aTarget selector: (SEL) aSelector;
#pragma mark -
#pragma mark Public methods
-(BOOL) isValid;
-(void) invalidate;
-(void) signal;
-(void) invoke;
-(void) scheduleInCFRunLoop: (CFRunLoopRef) aRunLoop forMode: (CFStringRef) mode;
@end
#pragma mark -
#pragma mark CFRunLoopSourceContext callbacks
void RunLoopSourceScheduleRoutine (void *info, CFRunLoopRef rl, CFStringRef mode);
void RunLoopSourcePerformRoutine (void *info);
void RunLoopSourceCancelRoutine (void *info, CFRunLoopRef rl, CFStringRef mode);
RunLoopContext.m
//
// RunLoopContext.m
// ETAClient-iPhoneOS
//
// Created by Daniel Reed on 9/7/10.
// Copyright 2010 N/a. All rights reserved.
//
#import "RunLoopContext.h"
@implementation RunLoopContext
#pragma mark -
#pragma mark Synthesize directives
@synthesize target;
@synthesize selector;
@synthesize context;
@synthesize source;
@synthesize runLoop;
#pragma mark -
#pragma mark Custom initializers
-(id) initWithTarget: (id) aTarget selector: (SEL) aSelector
{
if (self = [super init])
{
target = aTarget;
selector = aSelector;
}
return self;
}
#pragma mark -
#pragma mark Public methods
-(BOOL) isValid
{
return CFRunLoopSourceIsValid(source);
}
-(void) invalidate
{
CFRunLoopSourceInvalidate(source);
}
-(void) signal
{
CFRunLoopSourceSignal(source);
CFRunLoopWakeUp(runLoop);
}
-(void) invoke
{
// Perform the target selector.
[target performSelector: selector];
}
-(void) scheduleInCFRunLoop: (CFRunLoopRef) aRunLoop forMode: (CFStringRef) aMode
{
// Setup the context.
context.version = 0;
context.info = self;
context.retain = NULL;
context.release = NULL;
context.copyDescription = CFCopyDescription;
context.equal = CFEqual;
context.hash = CFHash;
context.schedule = RunLoopSourceScheduleRoutine;
context.cancel = RunLoopSourceCancelRoutine;
context.perform = RunLoopSourcePerformRoutine;
// Store the configured runloop and mode.
runLoop = aRunLoop;
mode = aMode;
// Create the CFRunLoopSourceRef.
source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
// Add the new CFRunLoopSourceRef to the indicated runloop.
CFRunLoopAddSource(runLoop, source, mode);
}
#pragma mark -
#pragma mark Overriden inherited methods
-(void) dealloc
{
// Invalidate.
[self invalidate];
// Set retained objects/values to nil.
target = nil;
selector = nil;
// Invoke the inherited dealloc method.
[super dealloc];
}
@end
#pragma mark -
#pragma mark CFRunLoopSourceContext callbacks
void RunLoopSourceScheduleRoutine(void* info, CFRunLoopRef rl, CFStringRef mode)
{
// Cast the info pointer to a RunLoopContext instance.
RunLoopContext* ctx = (RunLoopContext*) info;
}
void RunLoopSourcePerformRoutine (void* info)
{
// Cast the info pointer to a RunLoopContext instance.
RunLoopContext* ctx = (RunLoopContext*) info;
if (ctx)
{
[ctx invoke];
}
}
void RunLoopSourceCancelRoutine (void* info, CFRunLoopRef rl, CFStringRef mode)
{
}