Swift 条件绑定的初始值设定项必须具有可选类型,而不是Int

Swift 条件绑定的初始值设定项必须具有可选类型,而不是Int,swift,Swift,获取此错误时会说: 条件绑定的初始值设定项必须具有可选类型,而不是Int 我一直在琢磨如何摆脱它。我必须使用可选绑定展开值心率。不要强制展开使用条件绑定展开的内容: if let hrAverage: Int = (oldHR1+oldHR2+oldHR3+oldHR4+heartRate!)/5 { print(hrAverage) } else { let hrAverage = (oldHR1+oldHR2+oldHR3+oldHR4) / 4 print(hr

获取此错误时会说:

条件绑定的初始值设定项必须具有可选类型,而不是Int


我一直在琢磨如何摆脱它。我必须使用可选绑定展开值心率。

不要强制展开使用条件绑定展开的内容:

if let hrAverage: Int = (oldHR1+oldHR2+oldHR3+oldHR4+heartRate!)/5 {
    print(hrAverage)
} else {
     let hrAverage = (oldHR1+oldHR2+oldHR3+oldHR4) / 4
     print(hrAverage)
}
如果在代码的其余部分需要平均值,这里有一种更简洁的方法:

if let hr = heartRate {
    let hrAverage: Int = (oldHR1 + oldHR2 + oldHR3 + oldHR4 + hr) / 5
    print(hrAverage)
} else {
    let hrAverage = (oldHR1 + oldHR2 + oldHR3 + oldHR4) / 4
    print(hrAverage)
}
oldHR1+oldHR2+oldHR3+oldHR4+心率/5不生成使用if-let语句所需的可选项

我建议你做以下几点:

let compactArray = [oldHR1, oldHR2, oldHR3, oldHR4] + [heartRate].compactMap{$0}
let hrAverage: Int = compactArray.reduce(0, +)/compactArray.count
现在有了一个变量,可以在if语句之外使用。如果您不需要,可以使用以下解决方案:

let average = {
    if let rate = heartRate {
        return (oldHR1 + oldHR2 + oldHR3 + oldHR4 + rate) / 5
    } else {
        return (oldHR1 + oldHR2 + oldHR3 + oldHR4) / 4
    }    
}()

编号的变量名(如oldHR1、oldHR2等)很好地表明您应该使用数组。在这种情况下,我建议您将这个运行平均值计算提取到它自己的数据类型中,这使得处理这些数据变得非常方便

if let rate = heartRate {
    let average = (oldHR1 + oldHR2 + oldHR3 + oldHR4 + rate) / 5
} else {
    let average = (oldHR1 + oldHR2 + oldHR3 + oldHR4) / 4
}

像oldHR1、oldHR2等有编号的变量名是一个很好的指示,表明您应该使用数组。好了,这是一个更好的答案-比我的更好@我仍然认为有更好的方法。我会很快删除无关的注释。是否存在一个同时包含.compactMap和.reduce的函数?你在这方面有点作弊,哈。但是你也可以做+heartRate==nil?[]:[heartRate]而不是+[heartRate]。compactMap。在检查可读性时,这似乎更具可读性是主观的,但我能理解你的观点。compactArray可以是一个var,并有条件地将heartRate附加到它,这也是可读的。编码风格是一天结束时的个人偏好。但性能是一个中立的标准:仅在[heartRate]上应用compactMap就可以删除oldHR1、oldHR2、oldHR3、oldHR4上任何不必要的压缩映射。谢谢你的贡献!为什么要将平均值作为IUO?如果您要返回nil,请将其设置为可选的,否则只需将其设置为常规变量-例如,您可以只返回0。它会使应用程序崩溃,即使变量隐式地表示不会崩溃nil@LinusGeffarth10不是一个普遍适用的默认值。如果我正在制作一个应用程序,当心率下降到某个阈值以下(比如30 bpm)时自动向急救服务部门发出警报,那么假设无心率的平均值为0,就会导致错误警报。optional的用途是允许调用方轻松决定如何处理nil情况,而不是让库作者强制使用0。如果调用方真的希望nil为0,他们可以这样做。平均值??0,简单。明白你的意思,接受。但是,为什么要加倍呢!而不是Double?@LinusGeffarth 2,但是,容易的nil合并的好处是语法成本高。零只可能出现在物体生命的最初一段时间。在平均值变为非零后,它们将永远不会再回到零。如果已知不可能再出现零,那么在整个代码中强制安全展开是没有意义的。例如,OP可能有一个采样UI,向用户指示正在采样心率,而不显示心率,直到可以采集足够的样本。@LinusGeffarth此测量心率后,请等待UI完成,并且有足够的样本可用,运行平均数将为非零,并且在对象的剩余生存期内将继续为非零。在这一点之前,完全可能从未调用过平均值函数。
struct RunningAverage {
    let maxSize: Int
    var samples: [Double]

    init(maxSize: Int, initialSamples samples: [Double] = []) {
        self.maxSize = maxSize
        self.samples = samples
    }

    mutating func addSample(_ newValue: Double) {
        samples.append(newValue)
        if maxSize < samples.count { samples.removeFirst() }
    }

    /// Will return `nil` when there are no samples.
    /// This allows for easy nil coalescence, without introducing the full burden of
    /// needing to unwrap in the case when the samples are known to be non-empty.
    var average: Double! {
        if self.samples.isEmpty { return nil }
        return samples.reduce(0, +) / Double(samples.count)
    }
}

var runningAverage = RunningAverage(maxSize: 5)
let mockSamples = 1...10
let runningAverages = mockSamples.map { mockSample -> Double in 
    runningAverage.addSample(Double(mockSample))
    return runningAverage.average
}
print(runningAverages) // => [1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]