Swift中有没有一个Kotlin等价的'with'函数?

i7uaboj4  于 2023-02-21  发布在  Swift
关注(0)|答案(2)|浏览(311)

在Kotlin中,我们可以更改以下内容

// Original code
var commonObj = ClassCommonObj()
 commonObj.data1 = dataA
 commonObj.data2 = dataB
 commonObj.data3 = dataC

// Improved code
var commonObj = ClassCommonObj()
with(commonObj) {
    data1 = dataA
    data2 = dataB
    data3 = dataC
}

但是,在Swift中,我是否可以使用等效的with函数?

// Original code
var commonObj = ClassCommonObj()
 commonObj.data1 = dataA
 commonObj.data2 = dataB
 commonObj.data3 = dataC
vngu2lb8

vngu2lb81#

不幸的是,Swift目前还没有这样的功能,但是,通过扩展的强大功能可以实现类似的功能:

protocol ScopeFunc {}
extension ScopeFunc {
    @inline(__always) func apply(block: (Self) -> ()) -> Self {
        block(self)
        return self
    }
    @inline(__always) func with<R>(block: (Self) -> R) -> R {
        return block(self)
    }
}

该协议和扩展提供了两个inline函数,其中一个函数用于返回处理后的对象,另一个函数与Kotlin和其他语言中的with严格相似(Visual Basic在90年代得到支持)。

用法

指定这些函数应应用于的类型:

extension NSObject: ScopeFunc {}

apply

let imageView = UIImageView().apply {
    $0.contentMode = .scaleAspectFit
    $0.isOpaque = true
}

这里我们创建了一个对象,一旦闭包被执行,修改后的对象就会被返回。

with

imageView.with {
    $0.isHidden = true
}

在Kotlin中等于with
最初基于this source code

注:

Swift编译器通常被认为是足够聪明的,能够决定一个函数是否应该被内联。很有可能,这两个函数会被内联,因为它们相对紧凑,即使没有严格指定@inline (__always)。无论哪种方式,你应该知道这个关键字不会影响它们的逻辑和结果,因为内联是关于optimizing the program的。

5tmbdcev

5tmbdcev2#

正如@Hexfire所说,到目前为止,还没有内置的Swift相当于Kotlin的with()。正如他所指出的,你或多或少可以自己编写一个。
我使用了一个与Kotlinwith()稍有不同的版本,它会自动返回修改后的元素(更类似于Kotlin的apply),我发现这个版本更清晰、更简洁,而且更有用。
这是我使用的版本:

@discardableResult
public func with<T>(_ item: T, _ closure: (inout T) -> Void) -> T {
  var mutableItem = item
  closure(&mutableItem)
  return mutableItem
}

它是全局声明的(因此不依赖于NSObject或扩展声明)。它还像我期望的那样处理可变性。在使用中,它看起来像:

let myWellDescribedLabel = with(UILabel()) {
  $0.attributedText = attributedStringTitle
  $0.isAccessibilityElement = true
  $0.numberOfLines = 1
}

不幸的是(或者是真的吗?参见注解),Swift在闭包中没有自语法,因此必须将传递的对象引用为$0(或者为闭包创建一个命名参数)。
在这里,处理可选项的withLet()也非常有用:

@discardableResult
public func withLet<T>(_ item: Optional<T>, _ closure: (inout T) -> Void) -> Optional<T> {
  guard let item = item else { return nil }
  return with(item, closure)
}

这些都是要点。

相关问题