数组的 Swift 5 动态类型

标签 swift generics

我在 Swift 中有以下代码:

class VolumeData <T> {
   private var volume: [T]

   init(with data:Data, width: UInt32, height: UInt32, depth: UInt32) {
      let size = width * height * depth
      volume = data.arrayFromData(size: Int(size))
   }
 }

class Volume: NSObject {

    private var rawVolume : Data?
    public var volume : VolumeData<Any>?
    public var header: Header?

 ....

    func loadVolume(_ name: String) {
        let filepath = Bundle.main.path(forResource: name, ofType: "vol")
        rawVolume = try? Data.init(contentsOf: URL(fileURLWithPath: filepath ?? ""))
        header = Header.init(from: ((rawVolume?.subdata(in: 0..<284))!))
        let volSize = header!.width * header!.height * header!.depth
        switch header!.type {
        case .FLOAT:
             volume = VolumeData<Float32>(with: (rawVolume?.subdata
             (in: 284..<volSize))!, width: header!.width, 
             height: header!.height, depth: header!.depth)
        default:
            volume = nil
        }
    }
}

为了完成:

extension Data {
    func arrayFromData<T> (size: Int) -> [T] {
       var arr:[T] = []
       for i in 0..<size {
           let offset = 4*i
           let d:T = self[offset..<offset+4].withUnsafeBytes { $0.pointee }
           arr.append(d)
        }
        return arr
    }
}

现在我有一个编译时错误:

Cannot assign value of type 'VolumeData<Float32>' (aka 'VolumeData<Float>') 
  to type 'VolumeData<Any>?'

谁能告诉我在 Swift 中实现这种动态泛型的正确方法?

最佳答案

VolumeData 之间转换类型,你总是可以使用 map在项目和类型转换上:

class VolumeData<T> {
    private var volume: [T]

    init(with data: Data, width: UInt32, height: UInt32, depth: UInt32) {
        let size = width * height * depth
        volume = data.arrayFromData(size: Int(size))
    }

    private init(volume: [T]) {
       self.volume = volume
    }

    func convert<TargetType>(conversionFn: (T) -> TargetType) -> VolumeData<TargetType> {
        return VolumeData<TargetType>(volume: self.volume.map(conversionFn))
    }
}

然后

case .FLOAT:
    let floatVolume = VolumeData<Float32>(
         with: (rawVolume?.subdata(in: 284..<volSize))!,
         width: header!.width, 
         height: header!.height,
         depth: header!.depth
    )
    volume = floatVolume.convert { $0 as Any }

然而,VolumeData<Any>不是很有用,根本没有用。在这种情况下,最好以某种方式保存原始类型。一种简单的方法是 enum具有相关值,例如:

enum VolumeDataType {
   case float(volume: VolumeData<Float32>)
}

然后:

class Volume: NSObject {

    private var rawVolume: Data?
    public var volume: VolumeDataType?
    public var header: Header?

    func loadVolume(_ name: String) {
        let filepath = Bundle.main.path(forResource: name, ofType: "vol")
        rawVolume = try? Data(contentsOf: URL(fileURLWithPath: filepath ?? ""))
        header = Header(from: ((rawVolume?.subdata(in: 0..<284))!))
        let volSize = header!.width * header!.height * header!.depth

        switch header!.type {
        case .FLOAT:
             volume = .float(volume: VolumeData<Float32>(
                 with: (rawVolume?.subdata(in: 284..<volSize))!,
                 width: header!.width, 
                 height: header!.height,
                 depth: header!.depth
             ))
        default:
           volume = nil
        }
    }

关于数组的 Swift 5 动态类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55502145/

相关文章:

ios - ScrollView 中的重叠元素

ios - 使用 swift 在 ios 中的 textview 中嵌入图像

java - 我有 2 个不同的类想要添加到 ArrayList 中,定义 ArrayList 的最佳方法是什么?

vb.net - 强类型泛型方法调用其参数的基类方法,而不是 T 中的隐藏方法?

c# - 转换通用类型 "as T"同时强制执行 T 的类型

c# - 如何在 C# 中创建 UserControl<T>?

swift - UITextChecker、Swift 的单词学习——不起作用

ios - 当滚动/索引超出数组范围时 UITableView 崩溃

swift - 如何创建引用自身的类型别名?

java - 如何克服访问者实现的类型删除问题