SwiftUI视图调用C++类属性报错,求解决方法
SwiftUI调用C++ std::string报错的解决办法
背景
我基于MVVM架构开发应用,视图用SwiftUI编写,ViewModel用C++实现。已经完成:
- 在MacBook Air M2(MacOS Sonoma 14.6.1)上通过Xcode 15.4创建SwiftUI基础项目
- 导入C++库
- 配置好C++互操作性编译设置及库搜索路径
相关代码
C++头文件(CppLibrary.hpp)
// // BartsCppLibrary.hpp // BartsCppLibrary // // Created by BRS on 16/08/2024. // #ifndef CppLibrary_ #define CppLibrary_ /* The classes below are exported */ #pragma GCC visibility push(default) #include <string> class CppLibrary { public: CppLibrary(); void IntPlus1(int32_t count); std::string text; }; #pragma GCC visibility pop #endif
C++实现文件(CppLibrary.cpp)
// // BartsCppLibrary.cpp // BartsCppLibrary // // Created by BRS on 16/08/2024. // #include <iostream> #include "CppLibrary.hpp" CppLibrary::CppLibrary() { text=""; } void CppLibrary::IntPlus1(int32_t count) { text=std::to_string(count+1); return; };
module.map
// // module.modulemap // BartsCppLibrary // // Created by BRS on 16/08/2024. // module BartsCppLibrary { header "CppLibrary.hpp" requires cplusplus export BartsCppLibrary }
SwiftUI ContentView.swift
// // ContentView.swift // Test // // Created by BRS on 11/08/2024. // import SwiftUI import BartsCppLibrary struct ContentView: View { var body: some View { @Observable var c = CppLibrary() ZStack{ Rectangle() .fill(Color("BackgroundColor")) .frame (width : 300, height : 200) .cornerRadius(20) .shadow(radius: 10) VStack { Text("BRS") .font(.title) Text ("Title") .italic() Spacer() HStack{ Image(systemName: "envelope.fill") Text("email") } HStack { Image(systemName: "link") Text("link") } HStack { Image(systemName: "location.fill") Text("Adress") } // 错误位置 Text(c.text) }.padding() }.frame(width:300, height:200) } } #Preview { ContentView() }
错误信息
Initializer 'init(_:)' requires that 'std.__1.string' (aka 'std.__1.basic_string<CChar, char_traits, allocator>') conform to 'StringProtocol'
解决办法
Swift和C++的字符串类型不直接兼容,std::string不能直接传给SwiftUI的Text组件,必须做类型转换,同时还要修正@Observable属性的位置错误:
1. 修正@Observable属性位置
@Observable修饰的属性不能放在body方法内部,必须移到结构体顶层:
struct ContentView: View { @Observable var c = CppLibrary() // 移到这里 var body: some View { // 原有视图代码... } }
2. 字符串类型转换方案
方案一:在C++层提供C风格字符串接口
修改C++类,添加返回const char*的方法,避免直接暴露std::string:
// 在CppLibrary.hpp的CppLibrary类中添加 const char* getText() const { return text.c_str(); }
Swift中调用时转换为Swift String:
Text(String(cString: c.getText()))
方案二:Swift扩展转换
给CppLibrary写Swift扩展,添加返回Swift String的计算属性:
extension CppLibrary { var swiftText: String { String(cString: text.c_str()) } }
视图中直接使用:
Text(c.swiftText)
方案三:直接在调用处转换
不需要修改C++代码,直接在Swift中做转换:
Text(String(cString: c.text.c_str()))
内容的提问来源于stack exchange,提问作者broos42
相关产品推荐
相关产品推荐

