Как уменьшить дублирующийся код при субкассировании CIFilter? - PullRequest
0 голосов
/ 09 июня 2019

Мое приложение требует CIFilter, каждый из которых имеет свой собственный CIKernel, который компилируется из Metal. Swift не позволяет создавать экземпляры CIFilter из собственного ядра, вместо этого мне нужно создать подкласс базового CIFilter для каждого нужного мне специального фильтра и использовать ядро ​​внутри вычисленного свойства outputImage. Все эти подклассы я определил внутри класса, который соответствует CIFilterConstructor и обслуживает экземпляр требуемого фильтра с помощью метода

filter(withName name: String) -> CIFilter?

Кажется, я не могу сделать что-либо доступным из внешней области видимости внутри подкласса CIFilter. Это означает, что каждый фильтр выглядит следующим образом:

class deuteranopiaFilter: CIFilter {
        var deuteranopiaKernel: CIKernel?

        override var name: String {
            get {
                return "deuteranopia"
            }
            set {}
        }

        override init() {
            super.init()
            guard let url = Bundle.main.url(forResource: "default", withExtension: "metallib"),
                let data = try? Data(contentsOf: url)
                else { fatalError("Unable to get metallib") }

            guard let deuteranopiaKernel: CIColorKernel = try? CIColorKernel(functionName: "deuteranopia",
                                                                             fromMetalLibraryData: data)
                else { fatalError("Couldn't create kernel \(self.name)") }
            self.deuteranopiaKernel = deuteranopiaKernel
        }

        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }

        override class func registerName(_ name: String,
                                         constructor anObject: CIFilterConstructor,
                                         classAttributes attributes: [String : Any] = [:]) {
            CIFilter.registerName("Deuteranopia", constructor: FilterManager(), classAttributes: attributes)
        }

        @objc dynamic var inputImage: CIImage?
        override var outputImage: CIImage? {
            if let input = inputImage {
                let src = CISampler(image: input)
                return self.deuteranopiaKernel?.apply(extent: input.extent, roiCallback: {return $1}, arguments: [src])
            } else {
                return nil
            }
        }
    }

Здесь много повторного использования кода. Создание библиотеки Metal и ядра, предоставление свойства name, функции класса register, свойства output image. Можно ли как-то избежать копирования всех этих копий для каждого фильтра, который у меня будет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...