Почему операция обратного вызова подписки Swift Movesense-API должна быть нулевой?

Я создаю интеграцию Swift с API Movesense, как показано здесь: https://bitbucket.org/suunto/movesense-mobile-lib/src/master/IOS/

Следуя примерам, приведенным в приложении Movesense Showcase, я подписался на уведомления о частоте пульса:

let request = MovesenseRequest(resourceType: .heartRate, method: .subscribe,
    parameters: nil)

    let operation = device.sendRequest(request, observer: self)

Я уверен, что мое устройство подключено и работает, потому что я могу без проблем получать информацию об энергии и температуре с помощью методов .get.

Проблема в том, что я не получаю ответов о частоте пульса от Movesense API. Проходя через api, я застреваю в методе запроса отправки, где обратные вызовы onCompletion и onEvent имеют нулевую операцию, поэтому он умирает, не отправляя ответ моему приложению.

internal func sendRequest(_ request: MovesenseRequest, serial: String,
                          observer: Observer) -> MovesenseOperation? {
    guard let mds = self.mdsWrapper,
          let jsonDecoder = self.jsonDecoder else {
        let error = MovesenseError.integrityError("MovesenseConnection::sendRequest error.")
        delegate?.onConnectionError(error)
        return nil
    }

    let resourcePath = "\(serial)/\(request.path)"
    let onCancel = {
        switch request.method {
            case .subscribe: mds.doUnsubscribe(resourcePath)
            default: return
        }
    }

    let operation = MovesenseOperationFactory.create(request: request,
                                                     observer: observer,
                                                     jsonDecoder: jsonDecoder,
                                                     onCancel: onCancel)

    // Decode response with the MovesenseOperation instance
    let onCompletion = { [connectionQueue, weak operation] (_ response: MDSResponse) in
        dump(response)
        guard let operation = operation else { return }
        connectionQueue.async {
            operation.handleResponse(status: response.statusCode, header: response.header,
                                     data: response.bodyData)
        }
    }

    switch request.method {
    case .get: mds.doGet(resourcePath, contract: request.contract, completion: onCompletion)
    case .put: mds.doPut(resourcePath, contract: request.contract, completion: onCompletion)
    case .post: mds.doPost(resourcePath, contract: request.contract, completion: onCompletion)
    case .del: mds.doDelete(resourcePath, contract: request.contract, completion: onCompletion)
    case .unsubscribe: mds.doUnsubscribe(resourcePath)
    case .subscribe:
        let onEvent = { [connectionQueue, weak operation] (_ event: MDSEvent) in
            dump(event)
            guard let operation = operation else {
                mds.doUnsubscribe(resourcePath)
                return
            }

            connectionQueue.async {
                operation.handleEvent(header: event.header,
                                      data: event.bodyData)
            }
        }

        mds.doSubscribe(resourcePath, contract: request.contract,
                        response: onCompletion, onEvent: onEvent)
    }

    return operation
}

Я знаю, что API работает, потому что код Movesense Showcase в репозитории работает нормально, но я не знаю, что я пропустил при настройке запроса, чтобы операция не обнулялась каждый раз. Что может вызвать эту ошибку?


person quillanu    schedule 18.03.2020    source источник


Ответы (1)


В конце концов я нашел свой ответ. Проблема была в слабой ссылке. Я нигде не сохранял эту операцию, поэтому при вызове обратного вызова операция всегда была нулевой, потому что ссылка была собрана сборщиком мусора. Решение заключалось в том, чтобы где-то сохранить операцию, возвращенную запросом на подписку, а затем удалить ссылку, когда вы откажетесь от подписки. Я лично использовал карту для хранения своих ссылок, но подойдет любой способ сохранить ссылку.

person quillanu    schedule 27.03.2020