在swift

时间:2018-01-31 12:07:34

标签: swift

我正在阅读博客,并且有一个类似下面的功能。我想知道以这种方式编写它的目的是什么?

  public func moveNinjaToBottomRight() {
    ninja.center = {
        let x = (frame.maxX - ninja.frame.width / 2)
        let y = (frame.maxY - ninja.frame.height / 2)
        return CGPoint(x: x, y: y)
    }()
}

2 个答案:

答案 0 :(得分:1)

这只是风格问题。

以这种方式编写函数:

public func moveNinjaToBottomRight() {
    ninja.center = {
        let x = (frame.maxX - ninja.frame.width / 2)
        let y = (frame.maxY - ninja.frame.height / 2)
        return CGPoint(x: x, y: y)
    }()
}

增加了功能目的的清晰度。一眼就可以看到它只是更新ninja.center而且您知道闭包内的代码正在计算新的中心。如果计算新中心需要更多的线路,情况尤其如此。

另一种写作方式是:

public func moveNinjaToBottomRight() {
    let x = (frame.maxX - ninja.frame.width / 2)
    let y = (frame.maxY - ninja.frame.height / 2)
    ninja.center = CGPoint(x: x, y: y)
}

在这种情况下,您必须先阅读所有行,然后才能了解该功能的实际功能。同样,对于如此短的功能,它几乎没有什么区别,但它需要更长的时间才能让读者更长时间地访问正在发生的事情。

如果闭包内的代码有特定用途,我建议仅使用此函数样式。在这种情况下,它正在创建CGPoint。如果闭包中的代码引起了诸如播放声音或更新用户界面等副作用,那么我相信第二个示例使用的命令式样式更有意义。

答案 1 :(得分:0)

支撑表达式后的parens被称为立即调用闭包,并具有在大括号内执行闭包的效果。

该样式通常用于初始化,它有助于您创建具有复杂初始化的属性:

public let ninja: UIImageView = {
    let image = UIImage(named: "ninja")
    let view = UIImageView(image: image)
    view.frame = CGRect(x: 0, y: 0, width: 45, height: 39)
    return view
}()

如您所示,在函数内使用它没有技术用途。除非编译器能够将其优化为更简单的逻辑,否则它可能效率低

它与样本中其他地方的变量初始化方式保持一致(假设您正在查看我找到的相同代码)。

在C编程中,通常只使用一对大括号来提供变量的本地范围。这是一种强大的编程实践,可确保它们不会在方法中进一步使用。

如果你想要实现这样的范围,那么Swift成语就是使用do { ...}

所以,要明确的是,你正在看的功能可以写得很清楚

public func moveNinjaToBottomRight() {
    let x = (frame.maxX - ninja.frame.width / 2)
    let y = (frame.maxY - ninja.frame.height / 2)
    ninja.center = CGPoint(x: x, y: y)
}

甚至

public func moveNinjaToBottomRight() {
    ninja.center = CGPoint(
      x: (frame.maxX - ninja.frame.width / 2), 
      y: (frame.maxY - ninja.frame.height / 2))
}

或者,如果有更多的逻辑,他们想要本地范围。

public func moveNinjaToBottomRight() {
    do {
        let x = (frame.maxX - ninja.frame.width / 2)
        let y = (frame.maxY - ninja.frame.height / 2)
        ninja.center =  CGPoint(x: x, y: y)
    }

    // more code here which wants to use x and y names 
    // but is not reusing the variables above
}