#swift #swiftui #compile-time-type-checking
#swift #swiftui #проверка типа во время компиляции
Вопрос:
Я пытаюсь создать версию настольной игры Splendor в SwiftUI исключительно в учебных целях. Я создаю представления стека токенов и получаю действительно запутанную ошибку. Каждый раз, когда я вношу изменения, canvas работает вечно, а затем выдает эту ошибку:
Компилятор не может выполнить проверку типа этого выражения в разумные сроки; попробуйте разбить выражение на отдельные подвыражения
Из того, что я вижу, мой код не содержит ошибок и выдержан в разумном стиле (хотя, пожалуйста, не стесняйтесь оставлять отзывы, если это можно улучшить). Ошибка, похоже, зависит от функции offset () в строке 11 — если я закомментирую ее, ошибка исчезнет, но в любом случае коду необходимо это смещение для работы. Я не понимаю, почему это должно быть так.
Сама ошибка предполагает разбиение кода на более мелкие фрагменты — но он и так довольно маленький!
В качестве пояснения, TokenView предназначен для создания токена с изображением драгоценного камня — подумайте о покерной фишке. TokenStackView предназначен для построения стека представлений токенов, каждый из которых немного смещен больше предыдущего, при этом последний чип расположен немного более косо. Логическое значение ‘ShowImage’ было моей попыткой упростить компиляцию для компилятора, но это не исправило ошибку.
В моем коде было еще несколько модификаторов, чтобы он хорошо выглядел, вписывался во фреймы и т.д., Но с тех пор я удалил их все в попытке исправить эту ошибку.
Мы были бы очень признательны за любую помощь в решении этой проблемы!
import SwiftUI
struct TokenStackView: View {
var gemType: GemType
var gemsCount: Int
var body: some View {
ZStack{
ForEach (0..<gemsCount-1) { index in
TokenView(gemType: self.gemType, showImage: false)
//This line here causes the error:
.offset(x: CGFloat(index * offsetFactor), y: CGFloat(-index * offsetFactor))
}
TokenView(gemType: self.gemType, showImage: true)
}
}
//Control Panel
let offsetFactor: CGFloat = 10
}
struct TokenStackView_Previews: PreviewProvider {
static var previews: some View {
TokenStackView(gemType: .ruby, gemsCount: 5)
}
}
Вот TokenStackView.swift:
import SwiftUI
struct TokenView: View {
var gemType: GemType
var showImage: Bool
var body: some View {
ZStack{
Circle()
.stroke(self.gemType.secondaryColour(), lineWidth: lineWidth)
.offset(x: -offset, y: offset)
if showImage {
Image(self.gemType.rawValue "-token")
.clipShape(Circle())
}
Circle()
.stroke(self.gemType.primaryColour() ,lineWidth: lineWidth)
}
.frame(width: frameWidthHeight, height: frameWidthHeight, alignment: .center)
}
let frameWidthHeight: CGFloat = 550
let lineWidth: CGFloat = 20
let offset: CGFloat = 10
}
struct TokenView_Previews: PreviewProvider {
static var previews: some View {
TokenView(gemType: .diamond, showImage: true)
}
}
Редактировать: исправлена незначительная ошибка в коде — ошибка компилятора сохраняется.
Комментарии:
1. Я думаю, я нашел проблему: мне нужно было сослаться на self.offsetFactor. В моем рабочем коде теперь есть эта строка: .offset(x: CGFloat (index) * self.offsetFactor, y: CGFloat(-index) * self.offsetFactor)
2. Спасибо Aseri за исправление!
Ответ №1:
Эти ошибки в основном возникают, когда вы делаете что-то неправильно, но разработчик не может сказать, что именно. иногда это случается, когда есть просто длинное выражение long, и компилятор недоволен им, и вам просто нужно разбить его на несколько выражений, и ошибка исчезнет.
в этом случае я увидел одну проблему с вашим кодом, которая, скорее всего, вызывает эту проблему. я не уверен, есть ли еще (вероятно, нет), но вот та, которую я нашел:
.offset(x: index * offsetFactor, y: -index * offsetFactor)
index
и offsetFactor
имеют тип Int
. вы должны просто обернуть их в CGFloat
, чтобы преобразовать в CGFloat
, потому что .offset(x:y:)
метод принимает CGFloats, а не целые числа:
.offset(x: CGFloat(index * offsetFactor), y: CGFloat(-index * offsetFactor))
Комментарии:
1. На самом деле у меня была именно эта строка — CGFloat (индекс * коэффициент смещения) и т.д. — Но я отредактировал ее, потому что думал, что это не нужно. На каком-то этапе я также определил сам offsetFactor как CGFloat, но изменил его на Int, чтобы посмотреть, исправит ли это проблему (очевидно, это не так). Независимо от того, сделаю ли я это, это не решит проблему!
2. то, что я сказал, определенно является проблемой, и ее необходимо исправить. когда вы ее исправляете, ошибка меняется? на что бы это изменилось?
3. Точно такая же ошибка! Я начал играть с кодом только из-за этой ошибки.
4. если вы измените тип
offsetFactor
на CGFloat, то вам не нужно оборачивать его вCGFloat
. либо изменитеoffsetFactor
обратно на Int, либо измените смещение на.offset(x: CGFloat(index) * offsetFactor, y: CGFloat(-index) * offsetFactor)
5. Спасибо, я исправлю это в своем коде. Ошибка проверки типов остается.
Ответ №2:
Следующий вариант скомпилирован хорошо. Протестировано с Xcode 12
TokenView(gemType: self.gemType, showImage: false)
.offset(x: CGFloat(index) * self.offsetFactor, y: CGFloat(-index) * self.offsetFactor)
Обновление: изменение на использование self
в self.offsetFactor
делает его компилируемым и с Xcode 11.2
Комментарии:
1. Моя ошибка остается. Может ли мой проект быть поврежден, или ошибка может быть в совершенно другой части моего кода? Закомментировав строку смещения, я могу скомпилировать все представления, что говорит о том, что остальной мой код не содержит ошибок.
2. Возможно, это действительно в другом коде, потому что я просто скопировал ваш и внес упомянутые изменения. Также разные версии Xcode могут генерировать разные ошибки. Вы можете предоставить больше кода, и я его протестирую.
3. У меня XCode 11.6 — это может иметь значение …?
4. Миллион благодарностей!! Я использовал ваш код, который изменил ошибку на что-то намного более полезное — моя ошибка заключалась в том, что мне нужно было ссылаться на self.offsetFactor. Ууууу!!!