Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving too many else-if statements in Swift 3

Problem: Given the inputs of the function, test each user to make sure they conform to the following conditions: 1. Each user in the users array cannot share a chatroom with the current user. (The Chatroom object has two properties 'firstUserId', and 'secondUserId'.
2. Each user in the users array is not the current user. 3. Each user in the users array is within 5 mile radius of current user.

At the call sight of the completion handler, I check if a User object has a value of true, if so, I show it to the current user as a potential match.

Now, I quickly brute forced this solution, but cringe every time I look at it. It just seems very inefficient. Any tips on a more elegant solution is much appreciated!

typealias validUsersCompletionHandler = (_ users: [User: Bool]) -> Void

private func validateNewUsers(currentUser: User, users: [User], chatrooms: [Chatroom], completionHandler: validUsersCompletionHandler?) {

    var results: [User: Bool] = [:]

    let currentUserCoords = CLLocation(latitude: currentUser.latitude, longitude: currentUser.longitude)

    for user in users {
        let newUserCoords = CLLocation(latitude: user.latitude, longitude: user.longitude)
        let distance = currentUserCoords.distance(from: newUserCoords)
        // // 1 mile = 1609 meters, 8046.72 = 5 miles.
        for chatroom in chatrooms {
            if currentUser.id == chatroom.firstUserId && user.id == chatroom.secondUserId {
                results[user] = false
            } else if currentUser.id == chatroom.secondUserId && user.id == chatroom.firstUserId {
                results[user] =  false
            } else if user.id == currentUser.id {
                results[user] = false
            } else if distance > 8046.72 {
                results[user] = false
            } else {
                results[user] = true
            }
        }
    }
    completionHandler?(results)
}

// ************************************************************************

// Below is my revised version of the method. Slightly more elegant I suppose?

// ************************************************************************

typealias validUsersCompletionHandler = (_ users: [User: Bool]) -> Void

private func validateNewUsers(currentUser: User, users: [User], chatrooms: [Chatroom], completionHandler: validUsersCompletionHandler?) {

    var results: [User: Bool] = [:]

    var isInRange = false

    var distance: Double = 0 {
        didSet {
            if distance > 8046.72 {
                isInRange = false
            } else {
                isInRange = true
            }
        }
    }

    let currentUserCoords = CLLocation(latitude: currentUser.latitude, longitude: currentUser.longitude)

    let currentUserId = currentUser.id

    for user in users {

        let userId = user.id

        let newUserCoords = CLLocation(latitude: user.latitude, longitude: user.longitude)

        distance = currentUserCoords.distance(from: newUserCoords)
        // // 1 mile = 1609 meters, 8046.72 = 5 miles.

        for chatroom in chatrooms {

            switch (currentUserId, userId, isInRange) {

            case (chatroom.firstUserId,chatroom.secondUserId, _), (_, _, false),(chatroom.secondUserId, chatroom.firstUserId, _), (_, currentUserId, _): results[user] = false

            default: results[user] = true

            }
        }

    }

    completionHandler?(results)

}

}


1 Answers

You can replace the if statement with switch... Or you can make tuple with (currentUserId, userId)

 //always check for optionals
    guard let currentUserId = currentUser.id, let userId = user.id, else{
    return
    }
   //The switch should have this format:
    switch (currentUserId, userId){
    //currentUserId == chatroom.firstUserId,  userId = chatroom.secondUserId)
    case (chatroom.firstUserId,chatroom.secondUserId):
    //do your things
    break
    case (chatroom.secondUserId,firstUserId):
    //do other things
    break
    default:
    break
    }

You can even use the case with declaration or comparing more options:

    switch value{
    case let x where value > 10:
    //When value is bigger than 10..etc
    default:
    break
    }

For better use, see: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html

Wish happy coding :)

like image 68
Dominik Bucher Avatar answered Dec 16 '25 18:12

Dominik Bucher



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!