如何CF发布必须返回的CGEventRef?

时间:2013-04-18 22:53:12

标签: xcode macos automatic-ref-counting macos-carbon core-foundation

我以两种方式拦截CGEventRef

  • 返回值NULL以终止事件
  • 通过CGEventRef
  • 为活动分配新的CGEventCreateKeyboardEvent()

Xcode的分析器告诉我,当我创建新事件时,我有潜在的泄漏。但是我需要返回那个新事件,所以我不能在那里CFRelease

  • 此Xcode错误有效吗?

  • 我应该在哪里正确CFRelease我创建的新CGEventRef?

  • 在null和new事件中,我不知道是否需要释放事件的原值。

  • 在方法名称附加“new”是否正确解决此问题?我认为可能是因为我创建了一个新事件。但其他案例呢?

- (CGEventRef)modifySomeKeyboardEvents:(CGEventRef)event {

    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
    NSLog(@"keycode: %d", keycode);

    switch (keycode) {
        case 0:
            NSLog(@"pressed 'a'");
            //Kill the event
            event = NULL;

            //Is a `CFRelease` of some kind needed here, to release the previous value?

            break;

        case 38:
            NSLog(@"pressed 'h'");

            //Send different character:
            CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
            CGEventRef newKeyEvent = CGEventCreateKeyboardEvent(eventSource, 1, true);
            CGEventSetIntegerValueField(newKeyEvent, kCGKeyboardEventKeycode, 51); // keycode '51' = backspace
            CFRelease(eventSource);

            event = newKeyEvent;

            //Can't CFRelease here, but somewhere?
            //CFRelease(newKeyEvent);

            break;

        default:
            break;
    }

    //Xcode error: "Potential leak of an object stored in newKeyEvent"
    return event;
}

1 个答案:

答案 0 :(得分:3)

The CGEventTapCallback documentation

  

新事件传回事件系统后,新事件将与原始事件一起发布。

因此,您负责发布新事件或旧事件。

分析仪不知道这一点,所以你需要告诉它。您可以通过将new置于方法名称的开头来使分析器静音,但使用copy可能会更清楚,这也会使警告静音:

- (CGEventRef)copyOrModifyKeyboardEvent:(CGEventRef)event {

(我猜newOrModifiedKeyboardEvent:也可以。)

我相信分析器也应该标记这一点,因为当你刚刚返回输入事件时它现在无法返回+1引用计数。但在我的测试中,它没有。 Xcode 4.6.2分析器没有给我这个方法的警告:

- (CGEventRef)copyOrModifyEvent:(CGEventRef)event {
    CGEventRef newEvent;
    if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 38) {
        newEvent = CGEventCreate(NULL);
    } else {
        newEvent = event;
    }
    return newEvent;
}