微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Data.subdatain :)结果为EXC_BAD_INSTRUCTION

如何解决Data.subdatain :)结果为EXC_BAD_INSTRUCTION

尝试检索Data对象的子数据时,应用程序崩溃并发出以下错误

线程1:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)

您可以在下面看到代码。这是Data扩展名。希望有人能解释为什么会崩溃。

public extension Data {
    /// Removes and returns the range of data at the specified position.
    /// - Parameter range: The range to remove. `range` must be valid
    /// for the collection and should not exceed the collection's end index.
    /// - Returns: The removed data.
    mutating func remove(at range: Range<Data.Index>) -> Self {
        precondition(range.lowerBound >= 0,"Range invalid,lower bound cannot be below 0")
        precondition(range.upperBound < self.count,upper bound exceeds data size")
        
        let removal = subdata(in: range) // <- Error occurs here
        removeSubrange(range)
        return removal
    }
}

编辑-添加调用功能

此扩展名是通过以下函数调用的:

func temporary(data: inout Data) -> Data {
    let _ = data.removeFirst()
    return data.remove(range: 0 ..< 3)
}

依次称为:

var data = Data([0,1,2,3,4,5])
let subdata = temporary(data: &data)

解决方法

您没有提供足够的信息让我们知道您崩溃的原因。我知道您的方法有误的一件事是您的前提条件。您将无法通过范围来删除集合中的所有元素。除此之外,您应该实现一个通用方法,该方法将使用RangeExpression而不是Range。这就是我实现这种方法的方式:

extension Data {
    /// Removes and returns the range of data at the specified position.
    /// - Parameter range: The range to remove. `range` must be valid
    /// for the collection and should not exceed the collection's end index.
    /// - Returns: The removed data.
    mutating func remove<R>(_ range: R) -> Data where R: RangeExpression,Index == R.Bound {
        defer { removeSubrange(range) }
        return subdata(in: range.relative(to: self))
    }
}

用法:

var data = Data([0,1,2,3,4,5])
let subdata = data.remove(0..<6)
print(Array(data),Array(subdata))  // "[] [0,5]\n"

要在尝试删除数据索引之前检查其数据索引是否包含特定范围,可以使用模式匹配运算符:

var data = Data([0,5])
let range = 0..<7
if data.indices ~= range {
    let subdata = data.remove(range)
    print(Array(data),Array(subdata))
} else {
    print("invalid subrange")  // "invalid subrange\n"
}

如果要对ClosedRange进行同样的操作,则需要在Range上实现自己的模式匹配运算符:

extension Range {
    static func ~=(lhs: Self,rhs: ClosedRange<Bound>) -> Bool {
        lhs.contains(rhs.lowerBound) && lhs.contains(rhs.upperBound)
    }
}

用法:

var data = Data([0,5])
let range = 0...5
if data.indices ~= range {
    let subdata = data.remove(range)
    print(Array(data),5]\n"
} else {
    print("invalid subrange")
}
,

该错误是由removeFirst函数引起的。该文档明确指出:

调用此方法可能会使此集合的所有保存索引无效。在使用任何可以更改其长度的操作更改集合后,请勿依赖先前存储的索引值。

似乎正是导致我的错误的原因。我已将removeFirst替换为remove(at:),现在可以使用了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。