Handling Callbacks

后端 未结 3 553
花落未央
花落未央 2021-02-04 20:00

I have a method in an objective-C class. It has 2 callback functions written in C. The class pointer i.e. self is passed to these functions as void *.

相关标签:
3条回答
  • 2021-02-04 20:05

    This is what Objective-C's selector is for: http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/NSInvocationOperation_Class

    The API isn't very intuitive, but its fine once you understand it

    You might need to do some refactoring as well, now there might be a better way, but when I had this problem my solution was to refactor and use InvoationOperation.

    0 讨论(0)
  • 2021-02-04 20:08

    Are your problems specifically with the IOKit callback routines? The problem with the specific example you gave is that the IOServiceMatchingCallback takes only 2 parameters, not 3. You need your RawDeviceAdded() and BulkTestDeviceAdded() callback functions to match the IOServiceMatchingCallback prototype and to accept self as the first parameter (refCon), not the 3rd. Also, you need to pass in self as the second-to-last parameter of IOServiceAddMatchingNotification() to get it passed back to you by the callback.

    A common method for handling C callbacks in Objective-C code is just to have a static function that forwards the callback to your instance. So, your example callback code would look like this:

    static RawDeviceAdded(void* refcon, io_iterator_t iterator)
    {
        [(MyClass*)refcon rawDeviceAdded:iterator];
    }
    
    @implementation MyClass
    - (void)setupCallbacks
    {
        // ... all preceding setup snipped
        kr = IOServiceAddMatchingNotification(gNotifyPort,kIOFirstMatchNotification, matchingDict,RawDeviceAdded,(void*)self,&gRawAddedIter );
        // call the callback method once to 'arm' the iterator
        [self rawDeviceAdded:gRawAddedIterator];
    }
    - (void)rawDeviceAdded:(io_iterator_t)iterator
    {
        // take care of the iterator here, making sure to complete iteration to re-arm it
    }
    @end
    
    0 讨论(0)
  • 2021-02-04 20:14

    Generally, callbacks in Objective-C are handled by passing a delegate object and a selector to perform on that delegate. For example, this method will call a method on its delegate after logging a message, passing both itself and the message that was logged.

    - (void)logMessage:(NSString *)message
              delegate:(id)delegate
        didLogSelector:(SEL)didLogSelector
    {
        NSLog(@"%@", message);
    
        if (delegate && didLogSelector && [delegate respondsToSelector:didLogSelector]) {
            (void) [delegate performSelector:didLogSelector
                                  withObject:self
                                  withObject:message];
        }
    }
    

    You might call it in code like this:

    - (void)sayHello
    {
        [logger logMessage:@"Hello, world"
                  delegate:self
            didLogSelector:@selector(messageLogger:didLogMessage:)];
    }
    
    - (void)messageLogger:(id)logger
            didLogMessage:(NSString *)message
    {
        NSLog(@"Message logger %@ logged message '%@'", logger, message);
    }
    

    You can also use objc_msgSend() directly instead, though you need to understand the Objective-C runtime enough to choose which variant to use and how to construct the prototype and function pointer through which to call it. (It's the mechanism by which message sends are actually implemented in Objective-C — what the compiler normally generates calls to in order to represent [] expressions.)

    0 讨论(0)
提交回复
热议问题