SoFunction
Updated on 2025-04-11

Swift uses SnapKit to imitate Kingfisher's third-party extension optimization

text

We usually useswiftWhen writing third-party extensions (categorized in OC), you may write methods directly into the extension, which is simple and convenient. However, when we look at some of the three parties that often use you (for example:Kingfisher、SnapKit) and so on will be derived with a simple parameter (for example:kfsnp), let’s explore how to use it, and then summarize its advantages and disadvantages

A brief thought on SnapKit expansion method

bySnapKitAs an example, using the following, it was found that thesnp

var iv = UIImageView();
 { make in
}

Intermediate variablessnpAs shown below,ConstraintViewIt is a rename (alias) for unifying different platforms

public extension ConstraintView {
    var snp: ConstraintViewDSL {
        return ConstraintViewDSL(view: self)
    }
}

Its previous version also directlyleftPrefixes, etc.snp_, call it directly, and I think everyone can see the purpose at a glance. That's right, avoiding the duplication of other extensions. Now it has been changed to the introductionsnpIndirectly calling, the actual logic is passedsnpCome to call, my personal guess is also based on mainstream applications to update. When calling, at least the classification API is tidy

Pros and cons:

  • 1. Introduce intermediate variablessnpAfter that, the first thing I feel is that when we call our classification, there are obviously not so many messy methods (this method OC can actually be used as a reference)
  • 2. Cancel itPrefix, reduces the amount of code, and when there is a duplicate name with other classes, you only need to replace itsnpThe variable name is just not required to be replacedallMethod, reduce naming obstacles
  • 3. By introducing this parameter between different parties, our calling module identification is more obvious, the functional module is clearer, and the maintenance is stronger.

A brief thought on Kingfisher extension method

byKingfisherAs an example, using the following, it was found that thekf

var iv = UIImageView();
(with: URL(string: ""))

In addition, during use, it is fully utilizedswiftFeatures,SnapKitMore elegant and efficient in use

//Declare a basic protocol, which must be of AnyObject type, which can be used to subsequently add protocols to the basic class.public protocol KingfisherCompatible: AnyObject { }
//Extend to implement this basic protocol so that our components can directly call the methods inside through .kf//This kf is similar to snap, except that it adds a generic to extend the limit between different classesextension KingfisherCompatible {
    public var kf: KingfisherWrapper<Self> {
        get { return KingfisherWrapper(self) }
        set { }
    }
}
//By the generic top one basic class one by one, through which the basic class we are extended can obtain the components we are extended//And through the generics of this basic class, different extension methods can be added to different types separatelypublic struct KingfisherWrapper<Base> {
    public let base: Base
    public init(_ base: Base) {
         = base
    }
}
// When the class following the protocol is UIImage, extend the methodextension KingfisherWrapper where Base: KFCrossPlatformImage {
    ...
}
// When the class following the protocol is KFCrossPlatformImageView, extend the method for itextension KingfisherWrapper where Base: KFCrossPlatformImageView {
    ...
}
...
//The above only defines a protocol that can be used after extension, and has not been applied to our basic components// Therefore, you only need to add extensions to the basic components and follow our protocolextension KFCrossPlatformImageView: KingfisherCompatible { }

The View without a name is an alias for the unified name of different platforms, as shown below (only for dispelling doubts)

#if os(iOS) || os(tvOS)
    public typealias ConstraintView = UIView
#else
    public typealias ConstraintView = NSView
#endif

Pros and cons:

  • 1. Introduce intermediate variableskfAfter that, the first thing I feel is that when we call our classification, there are obviously not so many messy methods (this method OC can actually be used as a reference)
  • 2. In addition, the prefix can be cancelled to reduce the amount of code. When there is a duplicate name with other classes, you only need to replace it.kfThe variable name is just for you, and you don't need to replace all methods, reducing naming obstacles
  • 3. By introducing this parameter between different parties, our calling module identification is more obvious, the functional module is clearer, and the maintenance is stronger.
  • 4. Introduce protocols and generics, introduce the same intermediate variable through protocols, extend different methods to different categories through generics, reduce invalid methods and code, etc., and make the structure clearer. From a certain perspective, it is an advanced version of the extension method.

Try imitating yourself

public protocol MarshalTest: AnyObject {}
struct Wrapper<T>  {
    public let base: T
    init(_ base: T) {
         = base
    }
}
extension MarshalTest {
    var ml: Wrapper<Self> {
        get { Wrapper(self) }
        set { }
    }
}
extension UIImageView : MarshalTest {}
extension Wrapper where T: UIImageView {
    func setImg() {
    }
}
extension Wrapper where T: UIView {
    func setBkg() {
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        var iv2 = UIImageView()
        ()  
    }
}

This test is successful. When we imitate, we can refer to this writing

at last

When we extend content for the default component ourselves, if we only extend only one class and function, we cansnpLikewise, you can directly introduce the intermediate variable extension. If our extensions are multiple categories and belong to a module, then we can imitate it.Kingfisher, make our functions clearer

The above is the detailed content of Swift SnapKit imitates Kingfisher's third-party extension optimization example. For more information about SnapKit's third-party extension, please follow my other related articles!