0

According to Apple documentation CFDictionaryRef and NSDictionary are Toll-Free Bridged Types. However, I get an AV in the following code, which MIGHT be because the bridge does not work with Delphi.

DADiskCopyDescription returns a CFDictionaryRef, which I wrap to a NSDictionary. The pointer is not NIL, but when I access a function in the object, I get an AV:

function osxGetRootVolumeUUID: string;
var lNSDictionary: NSDictionary;
    lDisk: DADiskRef;
    lCFUrl: CFURLRef;
    lSession: DASessionRef;
    lUUID: CFUUIDRef;
begin
  result := '';
  lSession := DASessionCreate(nil);
  lCFUrl := TNSURL.OCClass.fileURLWithPath(StrToNSStr('/'));
  lDisk := DADiskCreateFromVolumePath(nil,lSession,lCFUrl);
  lNSDictionary := TNSDictionary.Wrap(DADiskCopyDescription(lDisk));

  lUUID := lNSDictionary.objectForKey(kDADiskDescriptionVolumeUUIDKey); //<- AV here

  if lUUID<>nil then
    result := CFStringRefToStr( CFUUIDCreateString(nil, lUUID));
  lNSDictionary.release;
  CFRelease(lCFurl);
end;

I also tried to use CFBridgingRelease as suggested in this SO question but it gives error SIGABRT (6):

lNSDictionary := TNSDictionary.Wrap(CFBridgingRelease(DADiskCopyDescription(lDisk))); //gives error: SIGABRT (6)

How to make it work?

PS. Basically I just want to get the UUID of the root volume on OSX. The function above is converted to Delphi from an Objective-C function we have used so far.

Edit

Another thing I have tried is to avoid using NSDictionary, but this gives an error too, which could indicate that the problem is something else:

lCFDictionaryRef := DADiskCopyDescription(lDisk);
lUUID := CFDictionaryGetValue(lCFDictionaryRef, kDADiskDescriptionVolumeUUIDKey); //<- AV here
Hans
  • 2,220
  • 13
  • 33

1 Answers1

1

To convert a CFDictionaryRef to a TNSDictionary you must do it like this :

  var LNSDict: NSDictionary;
      LCFDict: CFDictionaryRef;

  LCFDict := DADiskCopyDescription(lDisk);
  try
    LNSDict:= TNSDictionary.Wrap(LCFDict );
  finally
    CFRelease(LCFDict);
  end;

so everything is good here, however i think maybe your av is in the way you access the object. don't forget in IOS to always use getObjectID and not the pointer to the object

ex: pass to ios api (xxx as ILocalObject).GetObjectID and never pass to the IOS api directly xxx

so maybe it's must be (kDADiskDescriptionVolumeUUIDKey as ILocalObject).GetObjectID or something similar

zeus
  • 12,173
  • 9
  • 63
  • 184
  • Thank you for your reply. Unfortunately kDADiskDescriptionVolumeUUIDKey cannot be typecasted to iLocalObject ([dccosx Error] uOSXutils.pas(136): E2015 Operator not applicable to this operand type). kDADiskDescriptionVolumeUUIDKey is generated by SDKtransform and I think it can be passed directly. – Hans Jun 16 '17 at 09:54
  • I just found that "(kDADiskDescriptionVolumeUUIDKey as ILocalObject).GetObjectID" was in fact the solution. The reason it did not work in the first place was that `kDADiskDescriptionVolumeUUIDKey` is implemented wrong in `Macapi.DiskArbitration`. When I implement it using `CocoaNSStringConst` instead of `CocoaPointerConst` then it works. – Hans Jan 23 '18 at 12:21