"CGFloat не конвертируется в" UInt8 "и другие проблемы CGFloat с Swift и Xcode 6 beta 4
В случае, если это освещает проблему, здесь исходный код Objective-C.
int x = (arc4random()%(int)(self.gameView.bounds.size.width*5)) - (int)self.gameView.bounds.size.width*2;
int y = self.gameView.bounds.size.height;
drop.center = CGPointMake(x, -y);
Я начал с этого кода. Строки 2 и 3 в порядке, я представляю их для ясности позже.
let x = CGFloat(arc4random_uniform(UInt32(self.gameView.bounds.size.width * 5))) - self.gameView.bounds.size.width * 2
let y = self.gameView.bounds.size.height
dropView.center = CGPointMake(x, -y)
В Xcode 6 beta 3 необходимо было вывести результат arc4random_uniform UInt32 в CGFloat, чтобы работа минус и умножение. Это больше не работает, и компилятор показывает ошибку:
'CGFloat не конвертируется в' UInt8
В примечаниях к выпуску указано:
"CGFloat теперь представляет собой отдельный тип с плавающей точкой, который обертывает либо Float на 32-разрядных архитектурах, либо Double на 64-разрядных архитектурах. Он обеспечивает все те же операции сравнения и арифметики Float и Double и может быть создан используя числовые литералы. Использование CGFloat изолирует ваш код от ситуаций, когда ваш код будет
! отлично подходит для 32-битных, но не работает при создании для 64-битных или наоборот. (17224725) "
Я просто делаю что-то неправильно с типами? Я даже не знаю, как лучше описать эту проблему, чтобы представить отчет об ошибке в Apple для бета-версии 4. Почти каждый проект Swift, который у меня есть, делает любую проблему с точками или прямой манипуляцией, попал в эту проблему, поэтому я ища какое-то здравомыслие.
Ответы
Ответ 1
Так как Swift не имеет неявных преобразований типов, вы должны указать все преобразования типов, которые имеют место. Что делает этот случай особенно утомительным, так это то, что в настоящее время Swift, похоже, не имеет прямых преобразований между CGFloat
и типами, такими как UInt32
, и вы должны пройти промежуточный тип, как вы обнаружили.
В конце концов, для arc4random_uniform
необходимы два двойных преобразования:
let bounds = CGRectMake(0.0, 0.0, 500.0, 500.0)
var x = CGFloat(UInt(arc4random_uniform(UInt32(UInt(bounds.size.width) * 5))))
x -= bounds.size.width * 2
let center = CGPointMake(x, -bounds.size.height)
Ответ 2
Была та же проблема... try wrapping
arc4random_uniform
с
Int()
как
Int(arc4random_uniform)
это сработало для меня... не знаю, почему у Swift/Xcode возникают проблемы с преобразованием unsigned INT's
Ответ 3
@Arkku предоставил правильное решение, поэтому однострочный для x является...
let x = CGFloat(UInt(arc4random_uniform(UInt32(UInt(self.gameView.bounds.size.width) * 5)))) - self.gameView.bounds.size.width * 2
Начиная с Xcode 6 beta 5, вы все равно можете использовать промежуточное преобразование, если хотите, и ваш код будет продолжать работать. Однако он больше не нужен, поэтому теперь работает так, как ожидалось.
let x = CGFloat(arc4random_uniform(UInt32(self.gameView.bounds.size.width * 5))) - self.gameView.bounds.size.width * 2
Поскольку исходный вопрос относится только к Xcode 6 beta 4, каков правильный способ справиться с этим вопросом? Есть ли историческая отметка? Должна ли быть удалена?
Ответ 4
TL; простые вызовы DR, вызывающие ошибки HCF: Halt и Catch Fire
Обратите внимание, что есть некоторые очевидные работы, связанные с работой, такие как реализация преобразования в CGFloat и из него:
Полностью законный, но не делайте этого:
extension Float {
func __conversion() -> CGFloat { return CGFloat(self) }
}
extension CGFloat {
func __conversion() -> Float { return Float(self) }
func __conversion() -> Double { return Double(self) }
}
extension Double {
func __conversion() -> CGFloat { return CGFloat(self) }
}
Я не заметил при наборе текста, но позже моя машина перегрелась и висела, а SourceKit пошла на 300-500%, а быстрый swceess + kernel_task занял более 10 гигабайт ОЗУ, потребляя все, что осталось от моих 16 концертов, Понадобилось много времени, чтобы отследить его до этого - это было не быстро.