- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是我的代码。它们是Objective-C语言:
- (void)objcMethod:(NSString *)format, ...
{
va_list args;
va_start(args, format);
NSString *msg = [[NSString alloc] initWithFormat:format arguments:args];
NSLog(@"%@", msg);
va_end(args);
va_start(args, format);
va_end(args);
}
va_list
,
va_start
,
va_end
)转换为快速语言?
最佳答案
通过@MartinR注释和对NSLog is unavailable的引用,您知道Swift可以通过使用Swift类型va_list
和CVarArg
来调用采用CVaListPointer
参数的(Objective-)C函数和方法。
许多常见的(Objective-C)可变参数函数和方法都有一个采用va_list
的同级,因此Swift中的这种支持提供了对它们的访问。
我还需要在Objective-C xxx.m文件中调用此swift方法。
但是,您希望采用另一种方法,并且编写了Objective-C方法的Swift可变参数函数版本后,您发现无法调用它。您试图问什么解决方案How do you call a Swift variadic method from Objective-C?,该问题的间接答案(您的问题被标记为重复)提供了一个提示-使用数组-但无法处理格式化打印所需的一般性键入方案。让我们看看是否可以到达那里...
(使用Xcode 10 / Swift 4.2,其他任何版本的Swift可能都不同。)
我们将使用以下Swift类作为基础:
class SwiftLog : NSObject
{
// Swift entry point
static func Log(_ format : String, args : CVarArg...)
{
withVaList(args) { LogV(format, $0)}
}
// Shared core
private static func LogV(_ format : String, _ args: CVaListPointer)
{
NSLogv(format, args)
}
}
CVarArg
documentation中列出了3287)。这里的私有核心功能微不足道,您可能希望做一些更多的事情。
Log()
,但是,正如您所发现的,由于
CVarArg
而不能。但是,Objective-C可以调用带有
NSObject
参数的Swift函数,而
NSObject
实现
CVarArg
,这使我们第一次尝试:
// Objective-C entry point
@objc static func Log(_ format : String, args : [NSObject])
{
withVaList(args) { LogV(format, $0) }
}
%@
设置格式,然后切换到Objective-C:
[SwiftLog LogObjects:@"%@|%@|%@|%@|%@|%@" args:@[@"42", @4.2, @"hello", @31, @'c', NSDate.new]];
42|4.2|hello|31|99|Sun Nov 11 08:47:35 2018
%6.2f
,
%x
等–并且字符以
99
出现。
NSNumber
值的功能,则可以。在Swift中,将
Log()
函数更改为:
@objc static func Log(_ format : String, args : [NSObject])
{
withVaList(args.map(toPrintfArg)) { LogV(format, $0) }
}
toPrintfArg
(它又大又丑),我们可以将此版本称为:
[SwiftLog Log:@"%@|%4.2f|%10s|%x|%c|%@" args:@[@"42", @4.2, @((intptr_t)"hello"), @31, @'c', NSDate.new]];
42|4.20| hello|1f|c|Sun Nov 11 08:47:35 2018
toPrintfArg
是做什么的呢?
NSNumber
对象。
NSNumber
对象并没有透露太多有关包装的内容,访问方法(
.doubleValue
,
.integerValue
等)会将包装的值转换为所请求类型的值并返回它。
NSNumber
是免费的桥接到Core Foundation类型的
CFBoolean
和
CFNumber
。前者用于布尔值(很明显!),后者用于所有其他数字类型,并且与
NSNumber
不同,它提供了一个返回包装值类型的函数,因此可以在不进行转换的情况下将其展开。使用这些信息,我们可以从
NSNumber
对象中提取原始值(专家,是的,请参见下文),所有在Swift中提取的值都将实现
CVarArg
,如下所示:
private static func toPrintfArg(_ item : NSObject) -> CVarArg
{
if let anumber = item as? NSNumber
{
if type(of:anumber) == CFBoolean.self { return anumber.boolValue }
switch CFNumberGetType(anumber)
{
case CFNumberType.sInt8Type: return anumber.int8Value
case CFNumberType.sInt16Type: return anumber.int16Value
case CFNumberType.sInt32Type: return anumber.int32Value
case CFNumberType.sInt64Type: return anumber.int64Value
case CFNumberType.float32Type: return Float32(anumber.floatValue)
case CFNumberType.float64Type: return Float64(anumber.doubleValue)
case CFNumberType.charType: return CChar(anumber.int8Value)
case CFNumberType.shortType: return CShort(anumber.int16Value)
case CFNumberType.intType: return CInt(anumber.int32Value)
case CFNumberType.longType: return CLong(anumber.int64Value)
case CFNumberType.longLongType: return CLongLong(anumber.int64Value)
case CFNumberType.floatType: return anumber.floatValue
case CFNumberType.doubleType: return anumber.doubleValue
case CFNumberType.cfIndexType: return CFIndex(anumber.int64Value)
case CFNumberType.nsIntegerType: return NSInteger(anumber.int64Value)
case CFNumberType.cgFloatType: return CGFloat(anumber.doubleValue)
}
}
return item;
}
NSNumber
对象解包(专家,是的,大多数情况,请参见下文),将其保留为原始值类型,同时将所有其他对象保留为
%@
格式(如
NSString
和
NSDate
对象所示)在示例中)。
"hello"
转换为
intptr_t
来传递,C整数类型的大小与指针大小相同,而不是指针值。在这种情况下,这很好,
va_list
本质上是无类型的字节鲍勃,并且格式告诉
NSLogv()
将下一个字节解释为哪种类型,转换为
intptr_t
会保留相同的字节/位并允许指针指向被包装为
NSNumber
。
NSValue
:
[NSValue valueWithPointer:"hello"]
toPrintfArg
中:
if let ptr = (item as? NSValue)?.pointerValue
{
return ptr.bindMemory(to: Int8.self, capacity: 1)
}
UnsafeMutablePointer<Int8>
的值,该值实现了
CVarArg
(对于后者,
capacity
是无关紧要的)。
NSNumber
,然后如上所述将其拆开,则类型可能会由于参数提升而改变(这意味着小于
int
的整数类型将作为
int
值传递,
float
值将作为
double
)在C中?答案可能是,但是
CVarArg
值的必需类型是提升的类型,因此在这种情况下它应该没有任何区别–与预期格式说明符相匹配的未包装值的类型。
NSDecimalNumber
呢?
NSDecimalNumber
(它是
NSNumber
的子类),则上述
toPrintfArg
会将其解压缩为
double
,并且必须使用浮点格式而不是
%@
。处理此问题留作练习。
关于objective-c - 如何将Objective-C语言(“va_list”,“va_start”,“va_end”)转换为快速语言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53220674/
我遵循了一本名为“Sitepoint Full Stack Javascript with MEAN”的书中的教程,我刚刚完成了第 6 章,应该已经创建了一个带有“数据库”的“服务器”。数据库只不过是
在 Jquery 中,我创建两个数组,一个嵌入另一个数组,就像这样...... arrayOne = [{name:'a',value:1}, {name:'b',value:2}] var arra
这个问题在这里已经有了答案: What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wa
我被放在别人的代码上,有一个类用作其他组件的基础。当我尝试 ng serve --aot(或 build --prod)时,我得到以下信息。 @Component({ ...,
我正在测试一些代码,并使用数据创建了一个 json 文件。 问题是我在警报中收到“[object Object],[object Object]”。没有数据。 我做错了什么? 这是代码:
我想打印 [object Object],[object Object] 以明智地 "[[{ 'x': '1', 'y': '0' }, { 'x': '2', 'y': '1' }]]"; 在 ja
我有一个功能 View ,我正在尝试以特殊格式的方式输出。但我无法让列表功能正常工作。 我得到的唯一返回是[object Object][object Object] [object Object]
在使用优秀的 Sim.js 和 Three.js 库处理 WebGL 项目时,我偶然发现了下一个问题: 一路走来,它使用了 THREE.Ray 的下一个构造函数: var ray = new THRE
我正在使用 Material UI 进行多重选择。这是我的代码。 {listStates.map(col => (
我的代码使用ajax: $("#keyword").keyup(function() { var keyword = $("#keyword").val(); if (keyword.
我遇到了下一个错误,无法理解如何解决它。 Can't resolve all parameters for AuthenticationService: ([object Object], ?, [o
我正在尝试创建一个显示动态复选框的表单,至少应选中其中一个才能继续。我还需要获取一组选中的复选框。 这是组件的代码: import { Component, OnInit } from '@angul
我正在开发 NodeJs 应用程序,它是博客应用程序。我使用了快速验证器,我尝试在 UI 端使用快速闪存消息将帖子保存在数据库中之前使用闪存消息验证数据,我成功地将数据保存在数据库中,但在提交表单后消
我知道有些人问了同样的问题并得到了解答。我已经查看了所有这些,但仍然无法解决我的问题。我有一个 jquery snipet,它将值发送到处理程序,处理程序处理来自 JS 的值并将数据作为 JSON 数
我继承了一个非常草率的项目,我的任务是解释为什么它不好。我注意到他们在整个代码中都进行了这样的比较 (IQueryable).FirstOrDefault(x => x.Facility == fac
我只是在删除数组中的对象时偶然发现了这一点。 代码如下: friends = []; friends.push( { a: 'Nexus', b: 'Muffi
这两个代码片段有什么区别: object = nil; [object release] 对比 [object release]; object = nil; 哪个是最佳实践? 最佳答案 object
我应该为其他人将从中继承的第一个父对象传递哪个参数,哪个参数更有效 Object.create(Object.prototype) Object.create(Object) Object.creat
我在不同的对象上安排不同的选择器 [self performSelector:@selector(doSmth) withObject:objectA afterDelay:1]; [self per
NSLog(@"%p", &object); 和 NSLog(@"%p", object); 有什么区别? 两者似乎都打印出一个内存地址,但我不确定哪个是对象的实际内存地址。 最佳答案 这就是我喜欢的
我是一名优秀的程序员,十分优秀!