views:

42

answers:

1

Here is the source files I'm currently developing. The idea behind this class is to contain a target object and selector which will be invoked in whatever CFRunLoop passed to scheduleInCFRunLoop. I need this to loop repeatedly without consuming all available processing time on the iPhone. Any help on completion will be most helpful, I've spent an entire day surfing the internet trying to find helpful information regarding custom CFRunLoop sources and I am yet to find anything useful for completing this class.

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)
{

}
A: 

Looks to me like you are re-implementing NSTimer. Is there a reason why you cannot use that class? It basically does the same thing.

St3fan
Well, I could use it, I'm simply choosing not to because I want to understand how to use RunLoops myself. Also, I'm not looking for an alternative, I'm looking for how to complete my solution. Thanks for your response.
drreed