iosswiftnsobjectswift-protocolsmetal-performance-shaders

Type 'MyWeights' does not conform to protocol 'NSCopying'


I am using Metal Performance Shader to set up a neural network, and encountered the issue when writing the weights initialization class: Type 'MyWeights' does not conform to protocol 'NSCopying'. What caused the error, and how to fix this?

PS. I tried to fix it by adding the copy() function, however I do not know what to return or what it means.

import Foundation
import MetalPerformanceShaders

class MyWeights: NSObject, MPSCNNConvolutionDataSource {
//Error: Type 'MyWeights' does not conform to protocol 'NSCopying'

/*
func copy(with zone: NSZone? = nil) -> Any {
    return self
}
*/

let name: String
let kernelWidth: Int
let kernelHeight: Int
let inputFeatureChannels: Int
let outputFeatureChannels: Int

var data: Data?

init(name: String, kernelWidth: Int, kernelHeight: Int,
     inputFeatureChannels: Int, outputFeatureChannels: Int,
     useLeaky: Bool = true) {
    self.name = name
    self.kernelWidth = kernelWidth
    self.kernelHeight = kernelHeight
    self.inputFeatureChannels = inputFeatureChannels
    self.outputFeatureChannels = outputFeatureChannels
}

func dataType() -> MPSDataType {
    return .float32
}

func descriptor() -> MPSCNNConvolutionDescriptor {
    let desc = MPSCNNConvolutionDescriptor(kernelWidth: kernelWidth,
                                           kernelHeight: kernelHeight,
                                           inputFeatureChannels: inputFeatureChannels,
                                           outputFeatureChannels: outputFeatureChannels)
    return desc
}

func weights() -> UnsafeMutableRawPointer {
    return UnsafeMutableRawPointer(mutating: (data! as NSData).bytes)
}

func biasTerms() -> UnsafeMutablePointer<Float>? {
    return nil
}

func load() -> Bool {
    if let url = Bundle.main.url(forResource: name, withExtension: "dat") {
        do {
            data = try Data(contentsOf: url)
            return true
        } catch {
            print("Error: could not load \(url): \(error)")
        }
    }
    return false
}

func purge() {
    data = nil
}

func label() -> String? {
    return name
}

}

Solution

  • It's telling you exactly what to do.

    You need to declare that your class conforms to the NSCopying protocol, and then you need to implement the only function in that protocol, copy(with:)

    class MyWeights: NSObject, MPSCNNConvolutionDataSource, NSCopying {
    
        func copy(with zone: NSZone? = nil) -> Any {
            return MyWeights(
              name: self.name,
              kernelWidth: self.kernelWidth,
              kernelHeight: self.kernelHeight,
              inputFeatureChannels: self.inputFeatureChannels,
              outputFeatureChannels: self.outputFeatureChannels,
              useLeaky: self.useLeaky)
        }
        //The rest of your class
    }