2011-02-15 102 views
4

我目前正在嘗試使用frank(並依次爲UISpec)爲我們的新iOS應用程序編寫一些驗收測試。雖然該框架支持觸摸作爲與視圖交互的基本方式,但它目前不支持任何更多涉及的手勢(例如捏,滑動等)。我至少需要添加滑動支持,因爲這是我們應用程序功能的核心,如果沒有它,我們的測試將會非常無用。如何以編程方式模擬滑動手勢?

如果我可以找到一種方法來模擬Cocoa中的事件,實現這應該相當簡單。如果您使用Apple的UIAutomation框架(see here),則可以發送滑動手勢,以便以外部方式生成這些事件。我在網上搜索過,但沒有找到任何人這樣做的例子(雖然有一個thread有人在之前要求類似的東西...)。

在您的幫助/想法非常感謝......

回答

6

我昨天花了好一會,在結束了這方面的工作在各種各樣的解決方案。我不與它完全滿意,但它是我現在做的最好的 - 如果任何人都可以提出任何改進或工作替代我歡迎他們......

總之,對於任何人試圖做一些事情類似。我基於this post中詳細介紹的API解決方案 - 我記錄了我想要模擬的事件序列,然後播放它們。唯一的麻煩是我無法使內置播放API工作(我在底部提到的評論中提到了同樣的崩潰)。經過一段時間在ASM土地上挖掘,我最終寫了自己的版本。

@implementation UIApplication (EventReplay) 

/// 
/// - replayEventsFromFile: 
/// 
- (void)replayEventsFromFile:(NSString *)filename 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES); 
    NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:filename]; 
    NSArray* eventList = [[NSArray arrayWithContentsOfFile:filePath] retain]; 
    [self replayEvents:eventList]; 
} 

/// 
/// - replayEvents: 
/// 
- (void)replayEvents:(NSArray *)events 
{ 
    if (!events.count) 
    return; 

    NSDictionary *eventDict = [events objectAtIndex:0U]; 
    GSEventRef thisEvent = GSEventCreateWithPlist((CFDictionaryRef)eventDict); 

    uint64_t eventTime = thisEvent->record.timestamp; 
    thisEvent->record.timestamp = mach_absolute_time(); 

    mach_port_t appPort = GSCopyPurpleNamedPort([[[NSBundle mainBundle] bundleIdentifier] UTF8String]); 
    GSSendEvent(&thisEvent->record, appPort); 
    mach_port_deallocate(mach_task_self(), appPort); 

    if (events.count <= 1) 
    return; 

    NSIndexSet *remainderIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, events.count - 1)]; 
    NSArray *remainingEvents = [events objectsAtIndexes:remainderIndexes]; 

    GSEventRef nextEvent = GSEventCreateWithPlist((CFDictionaryRef)[remainingEvents objectAtIndex:0U]); 
    NSTimeInterval nextEventDelay = GetTimeDelta(nextEvent->record.timestamp, eventTime); 

    if (nextEventDelay > 0.05) 
    [self performSelector:@selector(replayEvents:) withObject:remainingEvents afterDelay:nextEventDelay]; 
    else 
    [self replayEvents:remainingEvents]; 

    CFRelease(nextEvent); 
    CFRelease(thisEvent); 
} 

@end 

上面的代碼片段顯示了我如何回放事件。我的實現是相當這些混沌 - 你會看到我只好做傻事迴避的事實,如果我一味地用一個定時器來安排接下來的活動有時不火 - 似乎是當延遲太小。您所看到的可怕的黑客似乎使事情的工作確定

不管怎麼說,希望這可以幫助別人以某種方式別人。

+1

是否與iOS 5的這種技術的工作?我如何包含GSEventRef? – 2011-12-11 06:16:11