Photovor
Photovor

Reputation: 403

Xcode updating label text from function

I'm having trouble with some objective-c in Xcode. I'm trying to adapt an example from the DiskArbitration framework, and I'm getting stuck. This example sets a callback whenever the framework sees a disk. From the callback, I want to update a label.

@interface AVRecorderDocument ()
    @property (assign) IBOutlet NSTextField *labelSpaceLeft;
@end

@implementation AVRecorderDocument
....

-id(init){
...
    DASessionRef sessionDA = DASessionCreate(kCFAllocatorDefault);
    DARegisterDiskAppearedCallback(sessionDA, kDADiskDescriptionMatchVolumeMountable, diskAppearedCallback, 0);
    DASessionScheduleWithRunLoop(sessionDA, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
...
}


static void diskAppearedCallback(DADiskRef disk, void* context)
{
    CFDictionaryRef description = DADiskCopyDescription(disk);
    NSLog(@"Disk appeared: %@", description);
    NSLog(@"Disk Name: %@", CFDictionaryGetValue(description, CFSTR("DADeviceModel")));

//  [_labelSpaceLeft setStringValue:[NSString CFDictionaryGetValue(description, CFSTR("DADeviceModel"))]];


    CFRelease(description);
}
...
@end

The commented line inside the static function is what i've tried, but I get a "Use of undeclared identifier" error.

I've also tried converting the function to a method, which the compiler is ok with, but then I don't know how to properly call this from the DARegisterDiskAppearedCallback line at the top.

-(void)diskAppearedCallback:(DADiskRef *)disk context:(void *)context{
    CFDictionaryRef description = DADiskCopyDescription(*disk);
    NSLog(@"Disk appeared: %@", description);

    NSString *spaceLeft = CFDictionaryGetValue(description, CFSTR("DADeviceModel"));

    NSLog(@"Disk Name: %@", CFDictionaryGetValue(description, CFSTR("DADeviceModel")));

    [labelSpaceLeft setStringValue:[NSString stringWithFormat: @"%@", spaceLeft]];


    CFRelease(description);
}

**UPDATE: Here is a gist of the project: https://gist.github.com/anonymous/cb1c5795536ca15ef4e3


Upvotes: 0

Views: 254

Answers (1)

Droppy
Droppy

Reputation: 9721

OK so the issue is that you are basically mixing C and Objective-C. The callback function diskAppearedCallback is a C function and is not part of that class, even though it is defined between @implementation and @end. It therefore doesn't have access to _labelSpaceLeft.

To fix the issue you need to get the callback function to call a method on that class instance, so when registering the callback, pass the instance in the last parameter. This is precisely what context pointers are for in callback functions.

DARegisterDiskAppearedCallback(sessionDA,
     kDADiskDescriptionMatchVolumeMountable,
     diskAppearedCallback,
     self);    // HERE

and then context in the callback function will be a pointer to the class instance:

static void diskAppearedCallback(DADiskRef disk, void* context) {
    CFDictionaryRef description = DADiskCopyDescription(*disk);
    NSLog(@"Disk appeared: %@", description);

    NSString *spaceLeft = CFDictionaryGetValue(description, CFSTR("DADeviceModel"));

    NSLog(@"Disk Name: %@", CFDictionaryGetValue(description, CFSTR("DADeviceModel")));

    // HERE
    AVRecorderDocument *instance = (AVRecorderDocument *)context;
    [instance.labelSpaceLeft setStringValue:spaceLeft];


    CFRelease(description);
}

Upvotes: 2

Related Questions