在Swift

时间:2017-08-06 07:11:14

标签: ios swift

我正在尝试找到最近的可能子视图。在我的应用中,有7个UIButton并且UILabel位于下方,边距为20.它不是子视图。

我想要什么?要用较少的努力找出最接近按钮的标签。

我目前在做什么?我正在函数中传递UIButton并计算从该按钮到所有标签的可能距离。然后对距离进行排序会导致上升并选择第一个对象以获得最小距离,这应该是我最近的标签。

internal func findNearByLabel(withRespectToButton button: UIButton) -> UILabel? {

    var distance = Array<CGFloat>()
    var labels: Array<UILabel> = self.view.subViews(type: UILabel.self)

    labels.forEach { (label) in
        distance.append(self.distance(label.frame.origin, button.frame.origin))
    }

    if !distance.isEmpty {
        let sortedDistance = Array.init(distance).sorted()
        let minDistance = sortedDistance.first!
        let indexOfMinDistance = distance.index(of: minDistance)!
        return labels[indexOfMinDistance]
    }

    return nil
}

internal func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
    let xDistance = a.x - b.x
    let yDistance = a.y - b.y
    return CGFloat(sqrt((xDistance * xDistance) + (yDistance * yDistance)))
}

extension UIView {
    func subViews<T : UIView>(type : T.Type) -> [T]{
        var all = [T]()
        for view in self.subviews {
            if let aView = view as? T{
                all.append(aView)
            }
        }
        return all
    }
}

什么是问题?没问题,它有效,但我想检查这是否是最佳解决方案,还是可以进行改进?

1 个答案:

答案 0 :(得分:3)

Just a few improvements using functional patterns.

// generic method, can be in a category
extension CGPoint {
    func distance(to point: CGPoint) -> CGFloat {
        // there is already a function for sqrt(x * x + y * y)
        return hypot(self.x - point.x, self.y - point.y)
    }
}

internal func findNearByLabel(withRespectToButton button: UIButton) -> UILabel? {
    // you don't really need the subViews method
    let labels = self.view.subviews.flatMap { $0 as? UILabel }
    // don't forget we got "map"
    let distances = labels.map { $0.frame.origin.distance(to: button.frame.origin) }

    // we zip both sequences into one, that way we don't have to worry about sorting two arrays
    let labelDistances = zip(labels, distances)
    // we don't need sorting just to get the minimum
    let closestLabel = labelDistances.min { $0.1 < $1.1 }

    return closestLabel?.0
}