如何用swift重写Objective-C宏扩展

Posted

技术标签:

【中文标题】如何用swift重写Objective-C宏扩展【英文标题】:How rewrite Objective-C Macro expand with swift 【发布时间】:2022-01-05 17:32:44 【问题描述】:

Objective-C 宏是这样的:

#define CALL_FUNC(classname, times, classfuncWithParamter) \ 
\
     for (int i = 0; i< times; i++) \
          [classname classfuncWithParamter]\
     \
\

调用 Objective-C:

CALL_FUNC(AnClass, 10, setName:@"test" withPhone:12345)

让我困惑的是这个for循环调用函数,宏可以做文本替换来做到这一点

在 Swift 中处理这个宏的最佳方法是什么?

【问题讨论】:

使用闭包。 docs.swift.org/swift-book/LanguageGuide/Closures.html Apple 在这里声明:developer.apple.com/documentation/swift/…,在 Swift 中没有类似宏的对应物。但正如他们在同一页上所说的那样,“您可以使用函数和泛型来实现相同的结果而无需任何妥协”。但是为了提供任何帮助,重要的是要知道如何使用这个宏:用它调用什么类型的类/函数。用例是什么——你为什么需要这个宏... 在您的情况下,它是一个带有 to 参数的函数:重复次数和 Class.classMethod 【参考方案1】:

正如人们在 cmets 中所说,您需要使用泛型和闭包。诀窍是,如果要支持多个参数,则必须多次声明“宏”:

// for functions with no arguments
func call<T>(times: Int, _ f: () -> T) 
    for i in 0..<times   f() 


// for functions with one argument
func call<A, T>(times: Int, _ f: (A) -> T, _ arg: A) 
    for i in 0..<times  f(arg) 


// for functions with two arguments
func call<A1, A2, T>(times: Int, f: (A1, A2) -> T, _ a1: A1, _ a2: A2) 
    for i in 0..<times  f(a1, a2) 


// for functions with three arguments
func call<A1, A2, A3, T>(times: Int, f: (A1, A2, A3) -> T, _ a1: A1, _ a2: A2, _ a3: A3) 
    for i in 0..<times  f(a1, a2, a3) 


// and so on...

对于您问题中的示例,调用看起来像这样:

call(times: 10, AnClass.setName(_:withPhone:), "test", 12345)

,或者你可以传递一个闭包,让代码更具可读性,像这样:

call(times: 10)  AnClass.setName("test", withPhone: 12345) 

,如果你选择这条路,你只能保留第一个call定义,没有参数的那个:func call&lt;T&gt;(_ times: Int, f: () -&gt; T)。在闭包中调用所需的函数也更加灵活,因为您可以在该闭包中支持任意数量的参数。

【讨论】:

感谢关闭是最好的方法,感谢您的回答

以上是关于如何用swift重写Objective-C宏扩展的主要内容,如果未能解决你的问题,请参考以下文章

对于桥接的 Objective-C 方法,这个 Swift 名称宏中缺少啥?

Swift - 从 ConstUnsafePointer<()> 转换

将 Objective-C 方法转换为 Swift [关闭]

从 Objective-C 访问 Swift 扩展

使用 Objective-C 类别扩展 Swift 类

在 Swift 中使用 Objective-C 扩展类