Модуль Swift, содержащий все методы расширения - PullRequest
0 голосов
/ 20 сентября 2018

Лично я предпочитаю методы расширения с префиксом в Swift.На первый взгляд легче угадать, является ли функция исходным классом или расширением.Кроме того, это делает рамки более пригодными для повторного использования в других проектах.Нам не нужно искать пространство имен, к которому относится метод фреймворка.Однако добавление префикса ко всем экземплярам и статическим методам в расширениях является немного исчерпывающим.По этой причине я хочу создать модуль, который содержит все методы расширения, будь то экземпляр или статика.

Я посмотрел на эту реализацию , и мне понравилось, но, к сожалению, толькоработает для методов экземпляра:

public protocol MyHelperCompatible {
    associatedtype someType
    var my: someType { get }
}

public extension MyHelperCompatible {
    public var my: MyHelper<Self> {
        get { return MyHelper(self) }
    }
}

public struct MyHelper<Base> {
    let base: Base
    init(_ base: Base) {
        self.base = base
    }
}

// All conformance here
extension UIColor: MyHelperCompatible { }

Используя это, мы можем получить доступ к методам экземпляра следующим образом:

let redImage = UIColor.red.my.toImage()

Знаете ли вы способ применения аналогичной логики для добавления модуляобрабатывать как экземпляры, так и статические методы?(например, UIColor.my.staticMethod()) Каким образом вы посоветуете использовать для этой проблемы?

1 Ответ

0 голосов
/ 20 сентября 2018

Вдохновленный подходом RxSwift, вот решение, которое предоставляет доступ как к экземпляру, так и к статическим членам расширения my.

Прежде всего, давайте объявим основу для расширения:

struct MyExtension<Target> {
    let target: Target

    init(_ target: Target) {
        self.target = target
    }
}

Давайте позволим типам соответствовать:

protocol MyExtensionCompatible { }

extension MyExtensionCompatible {
    // instance extension
    var my: MyExtension<Self> { return MyExtension(self) }

    // static extension
    static var my: MyExtension<Self>.Type { return MyExtension<Self>.self }
}

Теперь давайте начнем играть и добавим соответствие UIColor:

extension UIColor: MyExtensionCompatible { }

extension MyExtension where Target == UIColor {

    static var customColor: UIColor { return UIColor.blue }

    func toImage() -> UIImage {
        return UIImage()
    }
}

Наконец, давайте использовать все, что мы создаливыше:

// the static property
let color = UIColor.my.customColor

// the instance function
let colorImage = color.my.toImage()

// foldoesn't compile, compile, we haven't declared UILabel as compatible
let color2 = UILabel.my

Что хорошо в вышеупомянутом подходе, так это то, что методы, объявленные как статические, будут доступны через свойство статического протокола, а экземпляры - через свойство протокола экземпляра.

...