"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 концертов, Понадобилось много времени, чтобы отследить его до этого - это было не быстро.