var x = jokes[arc4random_uniform(UInt32(jokes.count))]

为什么这行代码会产生这样的错误?
编写此代码时
var x = jokes[Int(arc4random()%jokes.count)]

出现此错误
Int is not convertible to UInt32

最佳答案

数组下标采用Int,而不是UInt32。您需要转换回:

let x = jokes[Int(arc4random_uniform(UInt32(jokes.count)))]

如果这对您来说有点吵,您可能需要创建一个函数来处理它:
func randomValueLessThan(x: Int) -> Int {
    return Int(arc4random_uniform(UInt32(x)))
}

或者您可以扩展数组来帮助:
extension Array {
    func uniformSelection() -> T {
        return self[Int(arc4random_uniform(UInt32(self.count)))]
    }
}

编辑:值得深入研究一下Int(arc4random()%jokes.count)这个案例,因为您可能会试图错误地修复它,并且它演示了为什么Swift的工作方式是这样的。
让我们从你的版本开始
let n = Int(arc4random() % jokes.count)
// => Could not find an overload for 'init' that accepts the supplied arguments

有点混乱。让我们简化一下看问题
let n = arc4random() % jokes.count
// => Cannot invoke '%' with an argument list of type '(UInt32, Int)'

这应该更清楚。arc4random返回aUInt32jokes.count()返回aInt。你不能把不同的类型模化。你得把他们带到同一个地方。好吧,我们想要一个Int,对吧?似乎很容易:
let n = Int(arc4random()) % jokes.count   // WARNING!!!! Never ever do this!!!!

为什么苹果如此迂腐,强迫我们手工操作?编译器不能自动转换它吗?好吧,上面的代码在64位处理器上运行良好,在32位处理器上大约有一半时间崩溃。这是因为通过调用Int(),您可以保证值始终在Int范围内。在32位处理器上,这是32位有符号范围。但是arc4random返回整个32位无符号范围内的值,其中包括许多不适合Int的数字。责怪!(或者如果您关闭了边界检查,那么它只会像在C中那样破坏您的数字,这是再好不过的了。)
这就是为什么Swift对整数转换很挑剔。当你转换的时候,你必须绝对确定这是一个安全的转换。在它编译之前,你不应该把它们到处乱扔。
也就是说,你当然不应该在arc4random上使用模数。But that's a different question.
另一方面,您会注意到randomValueLessThan()中的数值强制转换会创建许多可能的无效情况。如果你通过一个小于0的数字,你将崩溃(不过,这并不奇怪)。如果传递的数字大于UInt32.Max,则也会崩溃,这稍微令人惊讶,但在大多数代码中是不太可能的。这一点是,通过添加这些类型转换,我们使randomValueLessThan成为一个部分函数。它不是在所有输入范围内定义的(它是“域”)。在“现实生活”编程中,我们总是这样做,我们只是希望它永远不会咬到我们。但斯威夫特试图帮助我们被咬的更少,使它更明显时,你打破类型安全。
uniformSelection也有类似的问题。它只为元素少于UInt32.Max的数组定义。这些有时感觉像是毫无意义的角落案例,它们是,直到突然它们不是,你的程序崩溃。(Array.subscript也是一个部分函数,因为它未定义数组范围之外的值。我实际上建议苹果返回一个选项来解释这个问题。他们不理我可能是明智的。)

关于ios - 找不到接受提供的参数的重载“init”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27862475/

10-12 04:31