【问题标题】:How to use CFDictionarySetValue in swift?如何快速使用 CFDictionarySetValue?
【发布时间】:2017-04-08 09:42:25
【问题描述】:

目前,我正在将硬件解码 Obj-C 代码转换为 Swift 版本。 (Xcode 8,Swift 3)。

我不知道如何设置字典来设置屏幕上的输出选项,我也不知道如何使用它。

以下代码在 Obj-C 项目中运行良好:

// set some values of the sample buffer's attachments
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);

我尝试了以下 Swift 代码,但出现了运行时错误:

// i got run-time error
let attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer!, true)
let dict = unsafeBitCast(attachments, to: CFMutableDictionary.self)
CFDictionarySetValue(dict, unsafeBitCast(kCMSampleAttachmentKey_DisplayImmediately, to: UnsafeRawPointer.self), unsafeBitCast(kCFBooleanTrue, to: UnsafeRawPointer.self))

CFString转换成UnsafeRawPointer有错吗?还是用CFDictionarySetValue方法不对?

这是我的错误日志。

2016-11-24 16:50:44.458 MyApp[35288:3519253] -[__NSSingleObjectArrayI __setObject:forKey:]: unrecognized selector sent to instance 0x6000002045a0
2016-11-24 16:50:44.466 MyApp[35288:3519253] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectArrayI __setObject:forKey:]: unrecognized selector sent to instance 0x6000002045a0'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010b02734b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010a0e421e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010b096f34 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    3   CoreFoundation                      0x000000010afacc15 ___forwarding___ + 1013
    4   CoreFoundation                      0x000000010afac798 _CF_forwarding_prep_0 + 120
    5   MyApp                             0x000000010937ac7a _TFC14MyApp16ViewerController21receivedRawVideoFramefT5frameGSaVs5UInt8_4withVs5Int32_T_ + 4890
    6   MyApp                             0x000000010937d8e2 _TFC14MyApp16ViewerController12MainCallBackfTVs5Int3212callbackCodeS1_8argumentGSqSv_7argSizeS1__T_ + 4242
    7   MyApp                             0x000000010937daed _TToFC14MyApp16ViewerController12MainCallBackfTVs5Int3212callbackCodeS1_8argumentGSqSv_7argSizeS1__T_ + 61
    8   MyApp                            0x000000010937dd56 _TTDFC14MyApp16ViewerController12MainCallBackfTVs5Int3212callbackCodeS1_8argumentGSqSv_7argSizeS1__T_ + 70
    9   MyApp                             0x000000010937dcfe _TTWC14MyApp16ViewerControllerS_18IJCallbackProtocolS_FS1_12MainCallBackfTVs5Int3212callbackCodeS2_8argumentGSqSv_7argSizeS2__T_ + 62
    10  MyApp                             0x00000001093b22b2 _TFC14MyApp11AppDelegate19MainCallBack_StreamfTVs5Int32S1_GSqSv_S1__T_ + 258
    11  MyApp                             0x00000001093d26d3 _TFZFC14MyApp19IJStreamCoreWrapper6AttachFTSv2ipSS4portSi_T_U_FTVs5Int32S1_GSqSv_S1_GSqSv__T_ + 355
    12  MyApp                             0x00000001093d2719 _TToFZFC14MyApp19IJStreamCoreWrapper6AttachFTSv2ipSS4portSi_T_U_FTVs5Int32S1_GSqSv_S1_GSqSv__T_ + 9
    13  MyApp                             0x00000001093ee176 _ZL8CallbackPN14CStreamManager9Session_TEiPvi + 70
    14  MyApp                             0x00000001093f09d3 _Z25StreamManagerThread_VideoPv + 3155
    15  libsystem_pthread.dylib             0x000000010e494aab _pthread_body + 180
    16  libsystem_pthread.dylib             0x000000010e4949f7 _pthread_body + 0
    17  libsystem_pthread.dylib             0x000000010e494221 thread_start + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

【问题讨论】:

  • 显示什么是运行时错误日志可能会有所帮助。
  • 我不确定确切的语法,但如果我没记错的话,CFDictionary 应该桥接到NSDictionary... 必须有一个简单的解决方案,涉及到 swift 关键字as
  • 它还桥接到 Swift 的原生 Dictionary。使用它。
  • Nicolas Miami 我已经使用了 ' as ' 关键字。但是,同样地,有一个错误。你是这个意思吗? : CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately as!UnsafeMutablePointer, kCFBooleanTrue as!UnsafeMutablePointer)
  • 艾哈迈德 F 谢谢。我附上了错误日志

标签: swift h.264 cfstring cfdictionary


【解决方案1】:

我只能通过以下方式来解决这个问题:

let attachments = CMSampleBufferGetSampleAttachmentsArray(buf!, createIfNecessary: true)
let dict = unsafeBitCast(CFArrayGetValueAtIndex(attachments, 0), to: CFMutableDictionary.self)
CFDictionarySetValue(dict,
                     unsafeBitCast(kCMSampleAttachmentKey_DisplayImmediately, to: UnsafeRawPointer.self),
                     unsafeBitCast(kCFBooleanTrue, to: UnsafeRawPointer.self))

我尝试了@Alexander的建议,虽然编译执行了,但是底层的CFDictionary并没有发生变异,也没有达到想要的结果。

//  let attachments = CMSampleBufferGetSampleAttachmentsArray(buf!, createIfNecessary: true) as! Array<Dictionary<String, Any>>
//  var dict = attachments[0]
//  dict[kCMSampleAttachmentKey_DisplayImmediately as String] = true

【讨论】:

    【解决方案2】:

    在第一个代码 sn-p 中,您调用了 CFArrayGetValueAtIndex,它返回一个您传递给 CFDictionarySetValue 的字典。

    在第二个代码 sn-p 中,您不调用 CFArrayGetValueAtIndex。您只需将数组传递给CFDictionarySetValue。由于数组不是字典,因此会出现致命错误。

    【讨论】:

      【解决方案3】:

      当您将代码转换为 Swift 时,最好了解程序的语义,然后重写匹配的 Swift 代码。不要试图只是一点一点地转换语法。

      CMSampleBufferGetSampleAttachmentsArray 为您返回对 CFArrayCFDictionary 实例的引用。将此 CFArrayRef 转换为 CFMutableDictionaryRef 的效果只是引用第一个实例。

      最好只使用 Swift 的原生类型。我无法提供确切的实现,因为我不确定正在使用的类型,但这是一个开始

      //TODO: give me a better name
      let array = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer!, true) as [[String: Bool]] //TODO:
      
      //TODO: give me a better name
      var firstDict = array[0]
      
      firstDict[kCMSampleAttachmentKey_DisplayImmediately as String] = true
      

      【讨论】:

      • 感谢您的建议。我会试试的。
      猜你喜欢
      • 2018-04-13
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多