For example, to record everything you've done during the for yourUIApplication:
recorder = [Recorder new];
[yourUIApplication _addRecorder:recorder];
[recorder release];
The command _addRecorder: adds the object to the application's event recorder array. You can remove your recorder at anytime with
[yourUIApplication _removeRecorder:recorder];
An event recorder must conform to the informal protocol
@protocol UIEventRecorder
-(void)recordApplicationEvent:(NSDictionary*)event;
@end
Here, "event" is a GSEvent converted to a plist using GSEventCreatePlistRepresentation(). You can add the event to an array and save that array for later reference, e.g.
@interface Recorder : NSObject { NSMutableArray* eventList; } @end
@implementation Recorder
-(id)init { if ((self = [super init])) eventList = [NSMutableArray new]; return self; }
-(void)save { [eventList writeToFile:@"events.plist" atomically:YES]; }
-(void)recordApplicationEvent:(NSDictionary*)event { [eventList addObject:event]; }
@end
Now say you want to play back the events you've previously collected. Just use this code:
NSArray* eventList = [NSArray arrayWithContentsOfFile:@"events.plist"];
float playbackRate = 1;
[app _playbackEvents:eventList atPlaybackRate:playbackRate messageWhenDone:target withSelector:@selector(done:)];
The higher the playback rate, the faster the system will run the events.
When the playback is finished, the "done:" selector will be called for "target". This selector must have a signature of
-(void)done:(NSDictionary*)detail;
the "detail" argument contains exactly 1 key, "UIApplicationEventRecordingDeliveryTimeUserInfoKey", which points to an array of the time the corresponding event happened.
This is very interesting; i'm trying to use this approach to help test my application, but i'm hitting a roadblock; calling the method to playback events causes an EXC_BAD_ACCESS error. My code looks like this, with eventList being retained beforehand:
ReplyDelete[[UIApplication sharedApplication] _playbackEvents:eventList atPlaybackRate:1.0 messageWhenDone:self withSelector:@selector(done:)];
any ideas what the cause might be?