Проблема: учитывая входные данные функции, протестируйте каждого пользователя, чтобы убедиться, что он соответствует следующим условиям: 1. Каждый пользователь в массиве users не может делить чат с текущим пользователем. (Объект Chatroom имеет два свойства: firstUserId и secondUserId.
2. Каждый пользователь в массиве пользователей не является текущим пользователем. 3. Каждый пользователь в массиве пользователей находится в радиусе 5 миль от текущего пользователя.

При вызове обработчика завершения я проверяю, имеет ли объект User значение true, если да, я показываю его текущему пользователю как потенциальное совпадение.

Я быстро применил это решение, но съеживаюсь каждый раз, когда смотрю на него. Это кажется очень неэффективным. Приветствуются любые советы по более элегантному решению!

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

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

// Ниже моя исправленная версия метода. Полагаю, чуть более элегантно?

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

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)

}

}

3
user6354073 28 Май 2017 в 21:17

2 ответа

Лучший ответ

Вы можете заменить оператор if на switch ... Или вы можете сделать кортеж с помощью (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
    }

Вы даже можете использовать регистр с объявлением или сравнить дополнительные параметры:

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

Для лучшего использования см .: https: // developer. apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html

Желаю счастливого кодирования :)

3
Dominik Bucher 28 Май 2017 в 18:34

В качестве альтернативы, вы можете хранить свои значения кортежа где-то в Struc (следует немного изменить логику), но вы можете сделать:

struct myBeautifulCases{
static let userIsCurrent = (_,currentUserId,_)
static let sameChatroom = (chatroom.secondUserId, chatroom.firstUserId, _)
static let sameChatroomAlt = (chatroom.secondUserId, chatroom.firstUserId, _)
static let isWithinRange = case (_, _, false)

} 

Теперь вы можете покрыть уродливые кортежи именами переменных, но вам следует немного изменить логику :) Желаю вам удачи и успешного проекта :)

0
Dominik Bucher 28 Май 2017 в 20:12