如何避免iOS中的“金字塔毁灭”?

3
我在我的代码中有一个“毁灭之塔”问题。

图片描述

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。有什么方法可以避免像我这样做?


你发布的大部分代码与你的问题无关,请只发布相关的代码。 - rmaddy
我希望他们能够看到我试图做什么的上下文。我将添加一张图片,展示毁灭金字塔的部分。 - code-8
我更新了我的帖子。 - code-8
3
万圣节的好恐怖的代码 :) 或许试着采用Codable,或者搜索一些开源解决方案,比如 ObjectMapper,用于 JSON 解析。 - pacification
你能否将其中一个答案标记为已接受的答案?我认为这个问题已经得到了解答。 - Alexander
显示剩余2条评论
1个回答

3
这是一个初步的近似结果。正如你所看到的,有很多可以被提取出来的重复模式。
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. Don't check for places.count > 0. If it's 0, the loop won't do anything.
  2. For every if statement whose block fully encompasses its parent block, I replaced it with a guard.
  3. Merged adjacent guard statements with a comma.
  4. Expressed failable type conversions as Optional.map(_:) expressions, rather than as separate let clauses in the guard statement
  5. Changed the i != j check into a where condition on the inner for loop.
  6. Changed this pattern:

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

    to this pattern:

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

由于没有明显的重复情况,这个提示表明将字典拆包成一个 Place 并放入方便初始化器中,该初始化器使用一个字典来初始化一个 Place?。更好的方法是直接使用Codable系统,让编译器为您合成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接