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)
}
}
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 :)