Тип выражения неоднозначен без дополнительной контекстной ошибки - PullRequest
0 голосов
/ 27 августа 2018

Как мне исправить этот код, чтобы он не выдавал ошибку: Тип выражения неоднозначен без дополнительного контекста?

var int = 0
while int < 100 {
        DispatchQueue.main.asyncAfter(deadline: .now() + int) { // change 2 to desired number of seconds
            // do stuff
        }
        int += 1
}

Код выполняется в очереди отправки в applicationDidEnterBackground, пытаясь заставить текст в речь работать в фоновом режиме.

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

Вы можете сделать DispatchTime математику с литералами

DispatchQueue.main.asyncAfter(deadline: .now() + 2)

но не с переменной Int, это неоднозначность. Перечисление DispatchTimeInterval для возможности передачи переменной Int

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(int))
0 голосов
/ 27 августа 2018

Тип выражения неоднозначен без контекста. * Ошибка 1002 * обусловлена ​​двумя фактами:

  1. Swift не знает, как добавить DispatchTime и * 1007.*.
  2. Из-за факта 1 Свифт не знает, как интерпретировать .now().

Свифт не знает, как добавить DispatchTime и Int

Это можно продемонстрировать с помощью:

let t = DispatchTime.now() + Int(5)

Двоичный оператор '+' нельзя применить к операндам типа 'DispatchTime' и'Int'

, но Swift знает, как добавить DispatchTime и Double:

let t = DispatchTime.now() + Double(5)

. Компилируется без ошибок.

Так почему же DispatchQueue.main.asyncAfter(deadline: .now() + 5) работает?

В этом случае Swift интерпретирует целочисленный литерал 5 как Double.Тип Double соответствует протоколу ExpressibleByIntegerLiteral, что позволяет вам делать:

let d: Double = 5

Так что в этом случае это работает, потому что 5 это не Int, это Double.

Из-за факта 1 Свифт не знает, как интерпретировать .now()

Когда вы пытались добавить Int к .now():

DispatchQueue.main.asyncAfter(deadline: .now() + int)

система логического вывода типа Swift запуталась.Swift знает, что хочет передать DispatchTime в asyncAfter(deadline:), но он больше не может понять, что такое .now(), потому что нет способа добавить DispatchTime и Int, чтобы получить DispatchTime, он решил, что .now() был не DispatchTime, а каким-то другим неизвестным типом.Таким образом, неоднозначное сообщение об ошибке происходит из-за неспособности Swift определить, что такое .now().

Если вы сделаете это явным, сказав DispatchTime.now(), то получите более ощутимую ошибку:

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + int)

Двоичный оператор '+' нельзя применить к операндам типа 'DispatchTime' и 'Int'

. В качестве дополнительного доказательства этой теории, если вы предоставите Swift способ добавления DispatchTime и Int, Swift доволен вашим исходным кодом:

func +(_ lhs: DispatchTime, _ rhs: Int) -> DispatchTime {
    return lhs + .seconds(rhs)
}

Так что же это за .seconds()?И как это помогает устранить ошибку?

Существует связанный enum тип DispatchTimeInterval, который имеет регистры microseconds(Int), milliseconds(Int), nanoseconds(Int), seconds(Int) и never.Swift знает, как добавить DispatchTime и DispatchTimeInterval, поэтому Swift может интерпретировать .seconds(int) как DispatchTimeInterval, что позволяет ему интерпретировать .now() как DispatchTime.

Почему дизайнеры Swift решили добавить Double к DispatchTime, а не Int?

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

Заключение

Ошибка исходит оттот факт, что вы запутали систему вывода типов Swift, пытаясь добавить Int к DispatchTime.

Исправления, как предлагали другие ответы:

  1. ИспользоватьDouble.

    или

  2. Используйте DispatchTimeInterval enum, чтобы явно отметить, что представляет собой Int.В вашем случае .seconds(int).

0 голосов
/ 27 августа 2018

Вам нужно использовать переменную double , чтобы добавить к .now().

var delay: Double = 0
while delay < 100 {
        DispatchQueue.main.asyncAfter(deadline: .now() + delay) { // change 2 to desired number of seconds
            // do stuff
        }
        int += 1
}
...