无法将Swift 4字符串传递给Obj-C ++-[_ SwiftValue dataUsingEncoding:]:无法识别的选择器已发送到实例

时间:2018-11-26 20:54:06

标签: swift nsstring selector objective-c++

我有一些像这样的Objective-C ++代码:

// header

@interface MyObjcClass

- (void) myMethod: (NSString *) text;

@end


// implementation

@implementation MyObjcClass

- (void) myMethod: (NSString *) text
{
    someInternalObject->useWstring(nsStringToWstring(text))
}

std::wstring nsStringToWstring(const NSString * text)
{
    NSData * data = [text dataUsingEncoding: NSUTF32LittleEndianStringEncoding];

    // and then some other stuff irrelevant to this question

    return std::wstring(pointerToNewString, pointerToNewString + stringLength);
}

@end

到目前为止直截了当;对我来说似乎很好。从Objective-C和Objective-C ++代码调用时,效果很好!但是,当Swift参与进来时...

func mySwiftFunc(text: String) {
    myObjcClassInstance.myMethod(text)
}

这似乎也很简单。编译器的翻译层自动将Swift的String桥接到Objective-C ++的NSString *。不幸的是,这是错误的……它似乎将其桥接到称为_SwiftValue的东西上。然后它传入了,我尝试在其上调用dataUsingEncoding:,但是显然_SwiftValue没有这样的选择器,所以我遇到了崩溃:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue dataUsingEncoding:]: unrecognized selector sent to instance 0x7f9ca7d63ee0'

我不知如何解决此问题。我不能在Swift中使用NSString并将其传递下去,因为编译器要求我需要传递一个Swift String

有什么办法解决这个问题?

这些解决方案中的任何一个都可以:

  • 强制生成Swift标头以接受NSString *而不是String
  • 一种将_SwiftValue转换为来自Objective-C ++的数据的方法
  • 任何标志,可让编译器或运行时知道将_SwiftValue转换为NSString * 之前尝试向其发送消息

环境

  • ObjC ++代码在Swift代码引用的模块化框架内;它们没有一起编译。
  • ObjC ++模块使用Xcode 8.3.3编译,而Swift代码则使用9.2编译。
  • 可能还有其他差异;这些项目中有很多活动部件。

1 个答案:

答案 0 :(得分:1)

我会尝试

this.createBoxes().then(function() {
    let template = document.querySelector('#pool');
    let app = document.querySelector(".app");
    for(let child of template.childNodes) {
        let clone = child.cloneNode(true);
        app.appendChild(clone);
    }
});

如果那行不通,请尝试:

func mySwiftFunc(text: String) {
     myObjcClassInstance.perform(#selector(NSSelectorFromString("myMethod:"), with: text as NSString)
}

在没有选择器名称func mySwiftFunc(text: String) { let selector : Selector = NSSelectorFromString("myMethod:") let methodIMP : IMP! = myObjcClassInstance.method(for: selector) unsafeBitCast(methodIMP,to:(@convention(c)(Any?,Selector,NSString)->Void).self)(myObjcClassInstance,selector,text as NSString) } 的情况下可能会实现字符串依赖性,但是我跳过了强制转换体操,因为这不是问题的本质。