如何解决Kotlin Native iOS字符串格式与vararg
基于this issue关于使用Nsstring
格式的信息,我尝试在使用vararg
时实现用于格式化的多平台实现,到目前为止还算没有运气。
我做了
- 添加了FoundationInterop.def
language = Objective-C
---
#import <Foundation/Nsstring.h>
Nsstring* format(Nsstring* format,...) {
va_list args;
va_start(args,format);
Nsstring* result = [[Nsstring alloc] initWithFormat:format arguments:args];
va_end(args);
return result;
}
- 将其编译为gradle
targets {
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
? presets.iosArm64 : presets.iosX64
// https://kotlinlang.org/docs/reference/mpp-dsl-reference.html#native-targets
fromPreset(iOSTarget,'ios') {
binaries {
}
compilations.main.cinterops {
FoundationInterop {
}
}
}
}
- 在
StringExtensions.kt
中创建了commonMain
expect class StringType
expect fun String.format(format: String,vararg args: Any?): StringType?
- 在
iosMain
中
actual typealias StringType = String
/**
* https://github.com/JetBrains/kotlin-native/issues/1834
*/
actual fun String.format(format: String,vararg args: Any?): StringType? {
return FoundationInterop.format(format,args as Any)
}
- 示例
val fmt = "http://geomag.bgs.ac.uk/web_service/GMModels/igrf/13/?latitude=%f&longitude=%f&altitude=0&date=%d-%02d-%02d&format=json"
val url = fmt.format(urlFmt,59.127934932762166,38.00503518930868,2020,1,3)
- 输出-如您所见,由于某种原因没有发生值替换
http://geomag.bgs.ac.uk/web_service/GMModels/igrf/13/?latitude=0.000000&longitude=0.000000&altitude=0&date=43344272-198763328-00&format=json
stringWithFormat
给出相同的结果
actual fun String.format(format: String,vararg args: Any?): StringType? {
return Nsstring.stringWithFormat(format,args as Any)
}
编辑2
创建的问题https://youtrack.jetbrains.com/issue/KT-42925
解决方法
我确认您对NSString.stringWithFormat
的看法。正如我们在JB官方解答中所读到的那样,该功能缺失
Svyatoslav Scherbina,我们可以在这里关注您的问题:KT-42925
作为一个可怕的解决方法,我建议使用类似的方法(警告:不详尽,没有很多索引计数检查...)
import platform.Foundation.NSString
import platform.Foundation.stringWithFormat
actual typealias StringType = String
actual fun String.format(format: String,vararg args: Any?): StringType? {
var returnString = ""
val regEx = "%[\\d|.]*[sdf]|[%]".toRegex()
val singleFormats = regEx.findAll(format).map {
it.groupValues.first()
}.asSequence().toList()
val newStrings = format.split(regEx)
for (i in 0 until args.count()) {
val arg = args[i]
returnString += when (arg) {
is Double -> {
NSString.stringWithFormat(newStrings[i] + singleFormats[i],args[i] as Double)
}
is Int -> {
NSString.stringWithFormat(newStrings[i] + singleFormats[i],args[i] as Int)
}
else -> {
NSString.stringWithFormat(newStrings[i] + "%@",args[i])
}
}
}
return returnString
}
但是请看它是否对您来说是有效的解决方法。
,您不能将Kotlin可变参数传递给C或Objective-C。 C variadics是编译时间。 这不是Kotlin特有的限制。您不能通过转发所有参数而从另一个可变C函数调用可变C函数。
NSString.stringWithFormat(format,args as Any)
这是不正确的。
该行使用args
(是Array
),将其强制转换为Any
并作为单个参数传递。
所以这基本上等同于类似的东西
[NSString stringWithFormat:format,createKotlinArray(/* all arguments here */)]
它没有达到您的期望。
因此KT-42925无效。 您的问题可能由缺少的功能之一解决了:
- stdlib(KT-25506)中的公用
String.format
。但这并不容易。 - 支持动态构建
va_list
,例如来自KotlinArray
(KT-42973)。在这种情况下,使用以下变体会很容易:https://developer.apple.com/documentation/foundation/nsstring/1407827-initwithformat
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。