【问题标题】:How to CFRelease a CGEventRef that must be returned?如何 CFRelease 必须返回的 CGEventRef?
【发布时间】:2024-01-19 00:28:01
【问题描述】:

我以两种方式拦截CGEventRefs:

  • 返回值NULL 杀死事件
  • 通过CGEventCreateKeyboardEvent() 为事件分配新的CGEventRef

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

  • 这个 Xcode 错误有效吗?

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

  • 在null和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;
}

【问题讨论】:

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


    【解决方案1】:

    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;
    }
    

    【讨论】:

    • 谢谢,非常有帮助的回答。
    • 基本的CGEventRef MyEventTapCallBack(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) 函数给出了相同的 Xcode 错误。那是 Apple 文档中使用的函数名称......你看到同样的错误吗?我真的需要重命名copy..吗?
    • 是的,您还需要重命名它。它需要以createcopy 开头。