【问题标题】:How do I avoid pyramid of doom - iOS?如何避免厄运金字塔 - iOS?
【发布时间】:2018-10-30 20:28:29
【问题描述】:

我的代码中有一个厄运金字塔。

if places.count > 0 {

        for i in 0..<places.count {
            for j in 0..<places.count {
                if let nameI = places[i]["name"] {
                    if let cityI = places[i]["city"] {
                        if let nameJ = places[j]["name"] {
                            if let cityJ = places[j]["city"] {
                                if let latI = places[i]["lat"] {
                                    if let lonI =  places[i]["lon"] {
                                        if let latitudeI = Double(latI) {
                                            if let longitudeI = Double(lonI) {
                                                if let latJ = places[j]["lat"] {
                                                    if let lonJ =  places[j]["lon"] {
                                                        if let latitudeJ = Double(latJ) {
                                                            if let longitudeJ = Double(lonJ) {

                                                                if(i != j) {

                                                                    let coordinateI = CLLocation(latitude: latitudeI, longitude: longitudeI)
                                                                    let coordinateJ = CLLocation(latitude: latitudeJ, longitude: longitudeJ)

                                                                    let distanceInMeters = coordinateI.distance(from: coordinateJ) // result is in meters
                                                                    let distanceInMiles = distanceInMeters/1609.344


                                                                    var distances = [Distance]()
                                                                    distances.append(Distance(
                                                                        distanceInMiles: distanceInMiles,
                                                                        distanceInMeters: distanceInMeters,
                                                                        places: [
                                                                            Place(name: nameI, city: cityI, lat: latitudeI, long: longitudeI, coordinate: coordinateI),
                                                                            Place(name: nameJ, city: cityJ, lat: latitudeJ, long: longitudeJ, coordinate: coordinateJ),
                                                                            ]
                                                                    ))
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

如何避免它?

是否有我应该遵循的技术或规则?

在 iOS 中,我们不得不使用大量的if-let。如何避免像我这样?

【问题讨论】:

  • 您发布的大部分代码与您的问题无关。请只发布相关代码。
  • 我希望他们看到我正在尝试做的事情的背景。我将添加显示末日金字塔部分的图片。
  • 所有表格视图代码如何与您的金字塔相关?这些扩展有什么关系?
  • 我更新了我的帖子。
  • 万圣节的好可怕代码:) 可能尝试采用Codable 或谷歌的一些开源解决方案,如ObjectMapper 进行json解析。

标签: ios swift optimization coding-style code-cleanup


【解决方案1】:

这是第一个近似值。如您所见,可以提取出很多重复的模式。

for (i, placeDictI) in 0..<places.enumerated() {
    guard
        let nameI = placeDictI["name"],
        let cityI = placeDictI["city"],
        let latitudeI = placeDictI["lat"].map(Double.init),
        let longitudeI =  placeDictI["lon"].map(Double.init),
        else { continue  }

        let coordinateI = CLLocation(latitude: latitudeI, longitude: longitudeI)
        let placeI = Place(name: nameI, city: cityI, lat: latitudeI, long: longitudeI, coordinate: coordinateI)

    for (j, placeDictJ) in places.enumerated() where i != j {
        guard  let nameJ = placeDictI["name"],
            let cityJ = placeDictI["city"],
            let latitudeJ = placeDictI["lat"].map(Double.init),
            let longitudeJ =  placeDictI["lon"].map(Double.init)
            else { continue }


        let coordinateJ = CLLocation(latitude: latitudeJ, longitude: longitudeJ)
        let placeJ = Place(name: nameJ, city: cityJ, lat: latitudeJ, long: longitudeJ, coordinate: coordinateJ)

        let distanceInMeters = coordinateI.distance(from: coordinateJ) // result is in meters // Editor's note: REALLY? I would have thought that a variable called "distanceInMeters" would store volume in litres! Silly me!
        let distanceInMiles = distanceInMeters/1609.344

        var distances = [Distance]()
        distances.append(Distance(
            distanceInMiles: distanceInMiles,
            distanceInMeters: distanceInMeters,
            places: [ placeI, placeJ ]
        ))
    }
}

这是我应用的转换:

  1. 不要检查places.count &gt; 0。如果为 0,则循环不会执行任何操作。
  2. 对于每个块完全包含其父块的if 语句,我将其替换为guard
  3. 用逗号合并相邻的guard 语句。
  4. 将失败的类型转换表示为Optional.map(_:) 表达式,而不是guard 语句中的单独let 子句
  5. i != j 检查更改为内部 for 循环上的 where 条件。
  6. 改变了这种模式:

     for i in 0..<array.count {
         use(array[i])
         use(array[i])
         use(array[i])
         //...
     }
    

    到这个模式:

    for (i, element) in array.enumerated() {
         use(element)
         use(element)
         use(element)
         //...
     }
    

鉴于没有明显的重复案例,这是一个很好的提示,解压缩成 Place 的 Dictionary 属于便利初始化程序,它需要一个从中初始化 Place? 的 dict。更好的是,只需使用 Codable 系统,并让编译器为您合成它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 2019-02-19
    • 2016-10-14
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多