Как не заморозить интерфейс и дождаться ответа? - PullRequest
0 голосов
/ 09 мая 2019

Я пытался с самого утра, но не достиг того, чего хотел.

Я пробовал DispatchQueue.main.async и блок завершения, но моя кнопка «Отправить» в пользовательском интерфейсе все еще зависает в ожидании данных, которые будут возвращены с сервера. Это мой код:

func createData(request:Crudpb_CreateRequest, with completion: @escaping (String) -> Void) throws {
    DispatchQueue.main.async {
        self.response = try! self.client.create(request) // <---- How to handle error for this server call when the server is not available or is down?
        completion(self.response.result)
    }
}

Я только что заметил, что я вызываю 1-й метод из следующего, который является синхронным унарным, что может быть причиной проблемы. Но опять же, я не знаю, как вызвать вторую функцию из следующих:

 /// Synchronous. Unary.
  internal func create(_ request: Crudpb_CreateRequest, metadata customMetadata: Metadata) throws -> Crudpb_CreateResponse {
    return try Crudpb_CrudServiceCreateCallBase(channel)
      .run(request: request, metadata: customMetadata)
  }
  /// Asynchronous. Unary.
  @discardableResult
  internal func create(_ request: Crudpb_CreateRequest, metadata customMetadata: Metadata, completion: @escaping (Crudpb_CreateResponse?, CallResult) -> Void) throws -> Crudpb_CrudServiceCreateCall {
    return try Crudpb_CrudServiceCreateCallBase(channel)
      .start(request: request, metadata: customMetadata, completion: completion)
  }

Код серверной стороны:

func (*server) Create(ctx context.Context, req *crudpb.CreateRequest) (*crudpb.CreateResponse, error) {

    var result string
    firstName := req.GetAccount().GetFirstName()
    lastName := req.GetAccount().GetLastName()
    //  id := gocql.TimeUUID()

    fmt.Println("Triggered CREATE function on Go Server " + firstName + " " + lastName + "! Yayy!")

    result = fmt.Sprintf("id for %s %s : %s", firstName, lastName, strconv.Itoa(rand.Intn(100)))
    return &crudpb.CreateResponse{
        Result: result,
    }, nil

Мне нужно, чтобы кнопка app / submit не зависала при получении результатов с сервера.

Пожалуйста, помогите.

Ответы [ 4 ]

1 голос
/ 09 мая 2019

Вместо этого используйте асинхронную функцию и вызовите блок завершения внутри create завершения функции.

func createData(request:Crudpb_CreateRequest, with completion: @escaping (String) -> Void) throws { 
try! self.client.create(request) { (response: Crudpb_CreateResponse?, result: CallResult) in 
  DispatchQueue.main.async {
// This is assuming your completion involves UI operations. Otherwise there is no need for this async call.

let stringOutput = String(data: result.resultData!, encoding: String.Encoding.utf8))
    completion(stringOutput)
    }
  }
}
1 голос
/ 09 мая 2019

Вы все еще выполняете работу в главном потоке. async возвращает только метод createData() до завершения задачи .. но задача все равно будет обрабатываться в основном потоке в некоторое время и в течение этого времени ваше приложение перестанет отвечать на запросы .. попробуйте вместо этого использовать глобальную очередь .. для поддержания основного потока в чистоте ..

Не забудьте выполнить всю работу над пользовательским интерфейсом в главном потоке после получения ответа.

0 голосов
/ 09 мая 2019

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

0 голосов
/ 09 мая 2019

Удалить блок DispatchQueue.main.async из метода createData

func createData(request:Crudpb_CreateRequest, with completion: @escaping (String) -> Void) throws {
    self.response = try! self.client.create(request)
    completion(self.response.result)
}

Использовать основную очередь только там, где вы обновляете пользовательский интерфейс из ответа API

myobj.createData(request: request, with: { string in
    print(string)//background thread
    DispatchQueue.main.async {
        self.label.text = sting//main thread
    }
})
...