【问题标题】:Delphi on OSX: how to convert CFDictionaryRef to NSDictionary?OSX 上的 Delphi:如何将 CFDictionaryRef 转换为 NSDictionary?
【发布时间】:2017-05-29 09:55:43
【问题描述】:

根据Apple documentationCFDictionaryRefNSDictionaryToll-Free Bridged Types。 但是,我在以下代码中得到了一个 AV,这可能是因为桥不适用于 Delphi。

DADiskCopyDescription 返回一个CFDictionaryRef,我将其包装为NSDictionary。指针不是NIL,但是当我访问对象中的一个函数时,我得到一个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;

我也尝试按照this SO question 中的建议使用CFBridgingRelease,但它给出了错误SIGABRT (6)

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

如何让它发挥作用?

PS。基本上我只想在 OSX 上获取根卷的UUID。上面的函数是从我们目前使用的 Objective-C 函数转换为 Delphi 的。

编辑

我尝试过的另一件事是避免使用NSDictionary,但这也会产生错误,这可能表明问题出在其他地方:

lCFDictionaryRef := DADiskCopyDescription(lDisk);
lUUID := CFDictionaryGetValue(lCFDictionaryRef, kDADiskDescriptionVolumeUUIDKey); //<- AV here

【问题讨论】:

    标签: macos delphi firemonkey


    【解决方案1】:

    要将 CFDictionaryRef 转换为 TNSDictionary,您必须这样做:

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

    所以这里一切都很好,但是我认为您的 av 可能妨碍您访问对象。不要忘记在 IOS 中始终使用 getObjectID 而不是指向对象的指针

    例如:传递给 ios api (xxx as ILocalObject).GetObjectID 并且永远不要直接传递给 IOS api xxx

    所以也许它必须是 (kDADiskDescriptionVolumeUUIDKey as ILocalObject).GetObjectID 或类似的东西

    【讨论】:

    • 感谢您的回复。不幸的是,kDADiskDescriptionVolumeUUIDKey 无法转换为 iLocalObject([dccosx 错误] uOSXutils.pas(136):E2015 运算符不适用于此操作数类型)。 kDADiskDescriptionVolumeUUIDKey是SDKtransform生成的,我觉得可以直接传递。
    • 我刚刚发现“(kDADiskDescriptionVolumeUUIDKey as ILocalObject).GetObjectID”实际上是解决方案。它首先不起作用的原因是kDADiskDescriptionVolumeUUIDKeyMacapi.DiskArbitration 中实现错误。当我使用CocoaNSStringConst 而不是CocoaPointerConst 实现它时,它就可以工作了。
    猜你喜欢
    • 2011-10-24
    • 2020-06-30
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多